From patchwork Mon Apr 8 21:18:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 139191 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id DB9FE43DD2; Mon, 8 Apr 2024 23:24:48 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1D4374064A; Mon, 8 Apr 2024 23:24:45 +0200 (CEST) Received: from mail-oa1-f43.google.com (mail-oa1-f43.google.com [209.85.160.43]) by mails.dpdk.org (Postfix) with ESMTP id C747B40633 for ; Mon, 8 Apr 2024 23:24:43 +0200 (CEST) Received: by mail-oa1-f43.google.com with SMTP id 586e51a60fabf-22edec341c2so1845700fac.0 for ; Mon, 08 Apr 2024 14:24:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712611483; x=1713216283; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dNwVMgvhyvxrr3NLBqyD4/IUsTt8vuh5Spk86OIFLjU=; b=pxP/9B/t3ki9Tc9adBNBvev+ncxYDaPv47/MiA7L4DQI7lTiNFewRAQPVvB72H/dn/ cE5m0kEMEXYOvIjoqlljgiAegxexvOAG7xy7bbNybFsyZa3hpK1meNy4PCG+MBhrS/30 soS04FtiHPm0vgHetw6AJuE57Y8hcUTAK86H6RdCBqP1Ihjenv1Y15IL2qqpgOcqhLa6 qCa/yI3a82vIutqqpuoCClpVQza2GRIfRI2z2V/OtXuO0m5BY8fq4VVDw875CM4i50RR obactR5up3ydfrk2AVlv9tSmpWZkw7ZYW/AuKLCMkxdNT+LQF9Bzu6DNOHU5sX4P9GBk +SJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712611483; x=1713216283; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dNwVMgvhyvxrr3NLBqyD4/IUsTt8vuh5Spk86OIFLjU=; b=N/5vOyjBFzWUBq14Z9/b+5F/fRG3Oih1ExupgEkjVLKEPgOajZlts3GpVAefHNlG2B Tm0+bn7baJd/lqOjzwiVjWrlRNpf6o4X9jNOz2bEb2JLbqGXWA5YC8HkI1vC59SiN1XL vPbFFBEngrbtLU3ge2qZjs+fGjE9Ko1joxQ1ZU++g1I0mChqqtE1TNz0rauNm67kogNR xoeopwioaAEFkwk1EmJHvYq6P/l/DXRG05UXaxTpduMj9xHVsvkgHH7EPe/agTNVv/pP YKNRk5ucnpJj6tJhrLrPstzpo+bQDBlZwjefrwf8zULXx8kXZMusgv0rLkSoJgYHr2j1 E0gQ== X-Gm-Message-State: AOJu0YzGFAAwA5+eUfdsbphkB8F6vEXCEgGP2A5Q2zggSmL78mQ/3PiI HP8/xb8IEkkTzR//GKLVSzMHUxOLen5z/WpE+tS9qsV3OLhrrUfZHQN2YWM96mImOqNMHViiHF4 zb0k= X-Google-Smtp-Source: AGHT+IF3Zd9CNKRsTyLh87OWVHsHzMHcdnK+ahOxrEAW/AqdhvXR248edOlNePp2BDD7gM35HzWmGA== X-Received: by 2002:a05:6870:72c8:b0:22e:af38:47ee with SMTP id o8-20020a05687072c800b0022eaf3847eemr10605878oak.58.1712611482912; Mon, 08 Apr 2024 14:24:42 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id f16-20020a633810000000b005e43cce33f8sm6924725pga.88.2024.04.08.14.24.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Apr 2024 14:24:42 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v7 1/8] net/tap: do not duplicate fd's Date: Mon, 8 Apr 2024 14:18:32 -0700 Message-ID: <20240408212438.414099-2-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240408212438.414099-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240408212438.414099-1-stephen@networkplumber.org> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The TAP device can use same file descriptopr for both rx and tx queues. This allows up to 8 queues (versus 4). Signed-off-by: Stephen Hemminger --- drivers/net/tap/meson.build | 2 +- drivers/net/tap/rte_eth_tap.c | 197 +++++++++++++++------------------- drivers/net/tap/rte_eth_tap.h | 3 +- drivers/net/tap/tap_flow.c | 3 +- drivers/net/tap/tap_intr.c | 7 +- 5 files changed, 92 insertions(+), 120 deletions(-) diff --git a/drivers/net/tap/meson.build b/drivers/net/tap/meson.build index 5099ccdff1..9cd124d53e 100644 --- a/drivers/net/tap/meson.build +++ b/drivers/net/tap/meson.build @@ -16,7 +16,7 @@ sources = files( deps = ['bus_vdev', 'gso', 'hash'] -cflags += '-DTAP_MAX_QUEUES=16' +cflags += '-DTAP_MAX_QUEUES=8' # input array for meson symbol search: # [ "MACRO to define if found", "header for the search", diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 69d9da695b..38a1b2d825 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -124,8 +124,7 @@ enum ioctl_mode { /* Message header to synchronize queues via IPC */ struct ipc_queues { char port_name[RTE_DEV_NAME_MAX_LEN]; - int rxq_count; - int txq_count; + int q_count; /* * The file descriptors are in the dedicated part * of the Unix message to be translated by the kernel. @@ -446,7 +445,7 @@ pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) uint16_t data_off = rte_pktmbuf_headroom(mbuf); int len; - len = readv(process_private->rxq_fds[rxq->queue_id], + len = readv(process_private->fds[rxq->queue_id], *rxq->iovecs, 1 + (rxq->rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER ? rxq->nb_rx_desc : 1)); @@ -643,7 +642,7 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs, } /* copy the tx frame data */ - n = writev(process_private->txq_fds[txq->queue_id], iovecs, k); + n = writev(process_private->fds[txq->queue_id], iovecs, k); if (n <= 0) return -1; @@ -851,7 +850,6 @@ tap_mp_req_on_rxtx(struct rte_eth_dev *dev) struct rte_mp_msg msg; struct ipc_queues *request_param = (struct ipc_queues *)msg.param; int err; - int fd_iterator = 0; struct pmd_process_private *process_private = dev->process_private; int i; @@ -859,16 +857,13 @@ tap_mp_req_on_rxtx(struct rte_eth_dev *dev) strlcpy(msg.name, TAP_MP_REQ_START_RXTX, sizeof(msg.name)); strlcpy(request_param->port_name, dev->data->name, sizeof(request_param->port_name)); msg.len_param = sizeof(*request_param); - for (i = 0; i < dev->data->nb_tx_queues; i++) { - msg.fds[fd_iterator++] = process_private->txq_fds[i]; - msg.num_fds++; - request_param->txq_count++; - } - for (i = 0; i < dev->data->nb_rx_queues; i++) { - msg.fds[fd_iterator++] = process_private->rxq_fds[i]; - msg.num_fds++; - request_param->rxq_count++; - } + + /* rx and tx share file descriptors and nb_tx_queues == nb_rx_queues */ + for (i = 0; i < dev->data->nb_rx_queues; i++) + msg.fds[i] = process_private->fds[i]; + + request_param->q_count = dev->data->nb_rx_queues; + msg.num_fds = dev->data->nb_rx_queues; err = rte_mp_sendmsg(&msg); if (err < 0) { @@ -910,8 +905,6 @@ tap_mp_req_start_rxtx(const struct rte_mp_msg *request, __rte_unused const void struct rte_eth_dev *dev; const struct ipc_queues *request_param = (const struct ipc_queues *)request->param; - int fd_iterator; - int queue; struct pmd_process_private *process_private; dev = rte_eth_dev_get_by_name(request_param->port_name); @@ -920,14 +913,13 @@ tap_mp_req_start_rxtx(const struct rte_mp_msg *request, __rte_unused const void request_param->port_name); return -1; } + process_private = dev->process_private; - fd_iterator = 0; - TAP_LOG(DEBUG, "tap_attach rx_q:%d tx_q:%d\n", request_param->rxq_count, - request_param->txq_count); - for (queue = 0; queue < request_param->txq_count; queue++) - process_private->txq_fds[queue] = request->fds[fd_iterator++]; - for (queue = 0; queue < request_param->rxq_count; queue++) - process_private->rxq_fds[queue] = request->fds[fd_iterator++]; + TAP_LOG(DEBUG, "tap_attach q:%d\n", request_param->q_count); + + for (int q = 0; q < request_param->q_count; q++) + process_private->fds[q] = request->fds[q]; + return 0; } @@ -1121,7 +1113,6 @@ tap_dev_close(struct rte_eth_dev *dev) int i; struct pmd_internals *internals = dev->data->dev_private; struct pmd_process_private *process_private = dev->process_private; - struct rx_queue *rxq; if (rte_eal_process_type() != RTE_PROC_PRIMARY) { rte_free(dev->process_private); @@ -1141,19 +1132,18 @@ tap_dev_close(struct rte_eth_dev *dev) } for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) { - if (process_private->rxq_fds[i] != -1) { - rxq = &internals->rxq[i]; - close(process_private->rxq_fds[i]); - process_private->rxq_fds[i] = -1; - tap_rxq_pool_free(rxq->pool); - rte_free(rxq->iovecs); - rxq->pool = NULL; - rxq->iovecs = NULL; - } - if (process_private->txq_fds[i] != -1) { - close(process_private->txq_fds[i]); - process_private->txq_fds[i] = -1; - } + struct rx_queue *rxq = &internals->rxq[i]; + + if (process_private->fds[i] == -1) + continue; + + close(process_private->fds[i]); + process_private->fds[i] = -1; + + tap_rxq_pool_free(rxq->pool); + rte_free(rxq->iovecs); + rxq->pool = NULL; + rxq->iovecs = NULL; } if (internals->remote_if_index) { @@ -1198,6 +1188,15 @@ tap_dev_close(struct rte_eth_dev *dev) return 0; } +static void +tap_queue_close(struct pmd_process_private *process_private, uint16_t qid) +{ + if (process_private->fds[qid] != -1) { + close(process_private->fds[qid]); + process_private->fds[qid] = -1; + } +} + static void tap_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid) { @@ -1206,15 +1205,16 @@ tap_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid) if (!rxq) return; + process_private = rte_eth_devices[rxq->in_port].process_private; - if (process_private->rxq_fds[rxq->queue_id] != -1) { - close(process_private->rxq_fds[rxq->queue_id]); - process_private->rxq_fds[rxq->queue_id] = -1; - tap_rxq_pool_free(rxq->pool); - rte_free(rxq->iovecs); - rxq->pool = NULL; - rxq->iovecs = NULL; - } + + tap_rxq_pool_free(rxq->pool); + rte_free(rxq->iovecs); + rxq->pool = NULL; + rxq->iovecs = NULL; + + if (dev->data->tx_queues[qid] == NULL) + tap_queue_close(process_private, qid); } static void @@ -1225,12 +1225,10 @@ tap_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid) if (!txq) return; - process_private = rte_eth_devices[txq->out_port].process_private; - if (process_private->txq_fds[txq->queue_id] != -1) { - close(process_private->txq_fds[txq->queue_id]); - process_private->txq_fds[txq->queue_id] = -1; - } + process_private = rte_eth_devices[txq->out_port].process_private; + if (dev->data->rx_queues[qid] == NULL) + tap_queue_close(process_private, qid); } static int @@ -1482,52 +1480,34 @@ tap_setup_queue(struct rte_eth_dev *dev, uint16_t qid, int is_rx) { - int ret; - int *fd; - int *other_fd; - const char *dir; + int fd, ret; struct pmd_internals *pmd = dev->data->dev_private; struct pmd_process_private *process_private = dev->process_private; struct rx_queue *rx = &internals->rxq[qid]; struct tx_queue *tx = &internals->txq[qid]; - struct rte_gso_ctx *gso_ctx; + struct rte_gso_ctx *gso_ctx = NULL; + const char *dir = is_rx ? "rx" : "tx"; - if (is_rx) { - fd = &process_private->rxq_fds[qid]; - other_fd = &process_private->txq_fds[qid]; - dir = "rx"; - gso_ctx = NULL; - } else { - fd = &process_private->txq_fds[qid]; - other_fd = &process_private->rxq_fds[qid]; - dir = "tx"; + if (is_rx) gso_ctx = &tx->gso_ctx; - } - if (*fd != -1) { + + fd = process_private->fds[qid]; + if (fd != -1) { /* fd for this queue already exists */ TAP_LOG(DEBUG, "%s: fd %d for %s queue qid %d exists", - pmd->name, *fd, dir, qid); + pmd->name, fd, dir, qid); gso_ctx = NULL; - } else if (*other_fd != -1) { - /* Only other_fd exists. dup it */ - *fd = dup(*other_fd); - if (*fd < 0) { - *fd = -1; - TAP_LOG(ERR, "%s: dup() failed.", pmd->name); - return -1; - } - TAP_LOG(DEBUG, "%s: dup fd %d for %s queue qid %d (%d)", - pmd->name, *other_fd, dir, qid, *fd); } else { - /* Both RX and TX fds do not exist (equal -1). Create fd */ - *fd = tun_alloc(pmd, 0, 0); - if (*fd < 0) { - *fd = -1; /* restore original value */ + fd = tun_alloc(pmd, 0, 0); + if (fd < 0) { TAP_LOG(ERR, "%s: tun_alloc() failed.", pmd->name); return -1; } + TAP_LOG(DEBUG, "%s: add %s queue for qid %d fd %d", - pmd->name, dir, qid, *fd); + pmd->name, dir, qid, fd); + + process_private->fds[qid] = fd; } tx->mtu = &dev->data->mtu; @@ -1540,7 +1520,7 @@ tap_setup_queue(struct rte_eth_dev *dev, tx->type = pmd->type; - return *fd; + return fd; } static int @@ -1620,7 +1600,7 @@ tap_rx_queue_setup(struct rte_eth_dev *dev, TAP_LOG(DEBUG, " RX TUNTAP device name %s, qid %d on fd %d", internals->name, rx_queue_id, - process_private->rxq_fds[rx_queue_id]); + process_private->fds[rx_queue_id]); return 0; @@ -1664,7 +1644,7 @@ tap_tx_queue_setup(struct rte_eth_dev *dev, TAP_LOG(DEBUG, " TX TUNTAP device name %s, qid %d on fd %d csum %s", internals->name, tx_queue_id, - process_private->txq_fds[tx_queue_id], + process_private->fds[tx_queue_id], txq->csum ? "on" : "off"); return 0; @@ -2001,10 +1981,9 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, dev->intr_handle = pmd->intr_handle; /* Presetup the fds to -1 as being not valid */ - for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) { - process_private->rxq_fds[i] = -1; - process_private->txq_fds[i] = -1; - } + for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) + process_private->fds[i] = -1; + if (pmd->type == ETH_TUNTAP_TYPE_TAP) { if (rte_is_zero_ether_addr(mac_addr)) @@ -2332,7 +2311,6 @@ tap_mp_attach_queues(const char *port_name, struct rte_eth_dev *dev) struct ipc_queues *request_param = (struct ipc_queues *)request.param; struct ipc_queues *reply_param; struct pmd_process_private *process_private = dev->process_private; - int queue, fd_iterator; /* Prepare the request */ memset(&request, 0, sizeof(request)); @@ -2352,18 +2330,17 @@ tap_mp_attach_queues(const char *port_name, struct rte_eth_dev *dev) TAP_LOG(DEBUG, "Received IPC reply for %s", reply_param->port_name); /* Attach the queues from received file descriptors */ - if (reply_param->rxq_count + reply_param->txq_count != reply->num_fds) { + if (reply_param->q_count != reply->num_fds) { TAP_LOG(ERR, "Unexpected number of fds received"); return -1; } - dev->data->nb_rx_queues = reply_param->rxq_count; - dev->data->nb_tx_queues = reply_param->txq_count; - fd_iterator = 0; - for (queue = 0; queue < reply_param->rxq_count; queue++) - process_private->rxq_fds[queue] = reply->fds[fd_iterator++]; - for (queue = 0; queue < reply_param->txq_count; queue++) - process_private->txq_fds[queue] = reply->fds[fd_iterator++]; + dev->data->nb_rx_queues = reply_param->q_count; + dev->data->nb_tx_queues = reply_param->q_count; + + for (int q = 0; q < reply_param->q_count; q++) + process_private->fds[q] = reply->fds[q]; + free(reply); return 0; } @@ -2393,25 +2370,19 @@ tap_mp_sync_queues(const struct rte_mp_msg *request, const void *peer) /* Fill file descriptors for all queues */ reply.num_fds = 0; - reply_param->rxq_count = 0; - if (dev->data->nb_rx_queues + dev->data->nb_tx_queues > - RTE_MP_MAX_FD_NUM){ - TAP_LOG(ERR, "Number of rx/tx queues exceeds max number of fds"); + reply_param->q_count = 0; + + RTE_ASSERT(dev->data->nb_rx_queues == dev->data->nb_tx_queues); + if (dev->data->nb_rx_queues > RTE_MP_MAX_FD_NUM) { + TAP_LOG(ERR, "Number of rx/tx queues %u exceeds max number of fds %u", + dev->data->nb_rx_queues, RTE_MP_MAX_FD_NUM); return -1; } for (queue = 0; queue < dev->data->nb_rx_queues; queue++) { - reply.fds[reply.num_fds++] = process_private->rxq_fds[queue]; - reply_param->rxq_count++; - } - RTE_ASSERT(reply_param->rxq_count == dev->data->nb_rx_queues); - - reply_param->txq_count = 0; - for (queue = 0; queue < dev->data->nb_tx_queues; queue++) { - reply.fds[reply.num_fds++] = process_private->txq_fds[queue]; - reply_param->txq_count++; + reply.fds[reply.num_fds++] = process_private->fds[queue]; + reply_param->q_count++; } - RTE_ASSERT(reply_param->txq_count == dev->data->nb_tx_queues); /* Send reply */ strlcpy(reply.name, request->name, sizeof(reply.name)); diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h index 5ac93f93e9..dc8201020b 100644 --- a/drivers/net/tap/rte_eth_tap.h +++ b/drivers/net/tap/rte_eth_tap.h @@ -96,8 +96,7 @@ struct pmd_internals { }; struct pmd_process_private { - int rxq_fds[RTE_PMD_TAP_MAX_QUEUES]; - int txq_fds[RTE_PMD_TAP_MAX_QUEUES]; + int fds[RTE_PMD_TAP_MAX_QUEUES]; }; /* tap_intr.c */ diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c index fa50fe45d7..a78fd50cd4 100644 --- a/drivers/net/tap/tap_flow.c +++ b/drivers/net/tap/tap_flow.c @@ -1595,8 +1595,9 @@ tap_flow_isolate(struct rte_eth_dev *dev, * If netdevice is there, setup appropriate flow rules immediately. * Otherwise it will be set when bringing up the netdevice (tun_alloc). */ - if (!process_private->rxq_fds[0]) + if (process_private->fds[0] == -1) return 0; + if (set) { struct rte_flow *remote_flow; diff --git a/drivers/net/tap/tap_intr.c b/drivers/net/tap/tap_intr.c index a9097def1a..1908f71f97 100644 --- a/drivers/net/tap/tap_intr.c +++ b/drivers/net/tap/tap_intr.c @@ -68,9 +68,11 @@ tap_rx_intr_vec_install(struct rte_eth_dev *dev) } for (i = 0; i < n; i++) { struct rx_queue *rxq = pmd->dev->data->rx_queues[i]; + int fd = process_private->fds[i]; /* Skip queues that cannot request interrupts. */ - if (!rxq || process_private->rxq_fds[i] == -1) { + if (!rxq || fd == -1) { + /* Use invalid intr_vec[] index to disable entry. */ /* Use invalid intr_vec[] index to disable entry. */ if (rte_intr_vec_list_index_set(intr_handle, i, RTE_INTR_VEC_RXTX_OFFSET + RTE_MAX_RXTX_INTR_VEC_ID)) @@ -80,8 +82,7 @@ tap_rx_intr_vec_install(struct rte_eth_dev *dev) if (rte_intr_vec_list_index_set(intr_handle, i, RTE_INTR_VEC_RXTX_OFFSET + count)) return -rte_errno; - if (rte_intr_efds_index_set(intr_handle, count, - process_private->rxq_fds[i])) + if (rte_intr_efds_index_set(intr_handle, count, fd)) return -rte_errno; count++; } From patchwork Mon Apr 8 21:18:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 139192 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6113943DD2; Mon, 8 Apr 2024 23:24:56 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 767A84067D; Mon, 8 Apr 2024 23:24:46 +0200 (CEST) Received: from mail-oa1-f43.google.com (mail-oa1-f43.google.com [209.85.160.43]) by mails.dpdk.org (Postfix) with ESMTP id 3DF0D40633 for ; Mon, 8 Apr 2024 23:24:44 +0200 (CEST) Received: by mail-oa1-f43.google.com with SMTP id 586e51a60fabf-22edf22ab08so2117933fac.2 for ; Mon, 08 Apr 2024 14:24:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712611483; x=1713216283; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=nQflKhToqXQy5/HFwbUg/VVDegoBYmRvbf0vhBIdcqA=; b=yd5FnNWXS2DIV2/qVEz0QlNth4nAh7gp8N0rxcG7gvzU4X9aqSN0uL7bylFBoeZeyQ EpOpntigxsdFPrbP9/y45Vg9cqDKLe1FRm11UyA8rWGoqoMlE9Cl5DL3thJSCsUMhecg mzp3OONOoNyhud5jrV7JTyWNcyIo5Ll7KyT3GlO0gASTrFdh6DRyOdXPdA9HMMgLiJVV tpaHIuAve5Keb0cgkSGO8rm4s9thKrzZz1coUP9vywl7z/lYLdy/b7ucfDDbtVRr03wA c5B7knS1iO/WhaRg06wOukij0sG9KwXj4sRrgDMzMK+0dVv68VGHepj6tqeONPX5tHNR UFLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712611483; x=1713216283; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=nQflKhToqXQy5/HFwbUg/VVDegoBYmRvbf0vhBIdcqA=; b=vrWTbzwnNQFTZPiUKBtNJUba0wiQ+uS35E8jmIMQ3LUeT38u6LXlYqLdVw0PsY7e45 I2m6/hT3Cbx867zjfIyflKq+3r1EJhwEC/tS/JNZO/6eMBf8R94uIYE7NYzYI9aLg3Qd npmsPQvQZv/4G7ZKi7F6+houSFR+lv83TJfvwifcoER7pZdWP0/SsligB1ItiQ20xm6L aDk2oJvm0nIujWlZC3KGe6zXoWN4D0YwZiV+7QAh2SztZDdYTn67ldUlM1ggpVtfQlXS wROSIik5nYEisYpl0olwOvWqaiT2ZXHhm5aUAdn+U2IEAgHCQZgn3Ggl0y/znhTBdDrU juLw== X-Gm-Message-State: AOJu0YzjwvpCiZNNIxKyD5AkJSpisaCuEWnKgYuBNn813jdK2Y71dCTL vUKmdHiKd4JktXmTx/dAgawX0U3f9ijYth2j8qL09PMQ+iiREqDkWFcLe1rqyNDYXn3TqOW2VMM tLhY= X-Google-Smtp-Source: AGHT+IENwBknIfqVraW6rG0Fh7ckbz/LsPsRFIFwWErdMoYjT8AloTqkjjEbWHizUheBFaiGiRb/bA== X-Received: by 2002:a05:6870:238e:b0:22e:c787:5fa2 with SMTP id e14-20020a056870238e00b0022ec7875fa2mr10838330oap.58.1712611483615; Mon, 08 Apr 2024 14:24:43 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id f16-20020a633810000000b005e43cce33f8sm6924725pga.88.2024.04.08.14.24.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Apr 2024 14:24:43 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v7 2/8] net/tap: remove unused fields Date: Mon, 8 Apr 2024 14:18:33 -0700 Message-ID: <20240408212438.414099-3-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240408212438.414099-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240408212438.414099-1-stephen@networkplumber.org> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The driver doesn't support these other hash types, and there is no reason to implement these in future. The rss_flows list was set but never used. Signed-off-by: Stephen Hemminger --- drivers/net/tap/rte_eth_tap.h | 4 +--- drivers/net/tap/tap_flow.c | 1 - drivers/net/tap/tap_rss.h | 6 ------ 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h index dc8201020b..1bcf92ce80 100644 --- a/drivers/net/tap/rte_eth_tap.h +++ b/drivers/net/tap/rte_eth_tap.h @@ -77,14 +77,12 @@ struct pmd_internals { int ioctl_sock; /* socket for ioctl calls */ int nlsk_fd; /* Netlink socket fd */ int flow_isolate; /* 1 if flow isolation is enabled */ - int flower_support; /* 1 if kernel supports, else 0 */ - int flower_vlan_support; /* 1 if kernel supports, else 0 */ int rss_enabled; /* 1 if RSS is enabled, else 0 */ int persist; /* 1 if keep link up, else 0 */ /* implicit rules set when RSS is enabled */ int map_fd; /* BPF RSS map fd */ int bpf_fd[RTE_PMD_TAP_MAX_QUEUES];/* List of bpf fds per queue */ - LIST_HEAD(tap_rss_flows, rte_flow) rss_flows; + LIST_HEAD(tap_flows, rte_flow) flows; /* rte_flow rules */ /* implicit rte_flow rules set when a remote device is active */ LIST_HEAD(tap_implicit_flows, rte_flow) implicit_flows; diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c index a78fd50cd4..8fccd599f0 100644 --- a/drivers/net/tap/tap_flow.c +++ b/drivers/net/tap/tap_flow.c @@ -1958,7 +1958,6 @@ static int rss_enable(struct pmd_internals *pmd, errno, strerror(errno)); return err; } - LIST_INSERT_HEAD(&pmd->rss_flows, rss_flow, next); } pmd->rss_enabled = 1; diff --git a/drivers/net/tap/tap_rss.h b/drivers/net/tap/tap_rss.h index dff46a012f..8766ffc244 100644 --- a/drivers/net/tap/tap_rss.h +++ b/drivers/net/tap/tap_rss.h @@ -21,12 +21,6 @@ enum hash_field { HASH_FIELD_IPV4_L3_L4, /* IPv4 src/dst addr + L4 src/dst ports */ HASH_FIELD_IPV6_L3, /* IPv6 src/dst addr */ HASH_FIELD_IPV6_L3_L4, /* IPv6 src/dst addr + L4 src/dst ports */ - HASH_FIELD_L2_SRC, /* Ethernet src addr */ - HASH_FIELD_L2_DST, /* Ethernet dst addr */ - HASH_FIELD_L3_SRC, /* L3 src addr */ - HASH_FIELD_L3_DST, /* L3 dst addr */ - HASH_FIELD_L4_SRC, /* TCP/UDP src ports */ - HASH_FIELD_L4_DST, /* TCP/UDP dst ports */ }; struct rss_key { From patchwork Mon Apr 8 21:18:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 139193 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 721C243DD2; Mon, 8 Apr 2024 23:25:04 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B0AEF4068E; Mon, 8 Apr 2024 23:24:47 +0200 (CEST) Received: from mail-il1-f169.google.com (mail-il1-f169.google.com [209.85.166.169]) by mails.dpdk.org (Postfix) with ESMTP id 216534064C for ; Mon, 8 Apr 2024 23:24:45 +0200 (CEST) Received: by mail-il1-f169.google.com with SMTP id e9e14a558f8ab-36a0f64f5e0so14039735ab.3 for ; Mon, 08 Apr 2024 14:24:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712611484; x=1713216284; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=QMpE4bJ02MY4VpUrTabgs0S4YJan2oEdqn4ZAnWdaHI=; b=A8sAmAU+/I1LZOR+UbkQDWOFx0RXy5YIPabEkfXtnDnKe482b5SMZh2zmcoea6rNX9 55fnl3Bigzx5vN/c3S4JJtNeXwahkP1e7EoT7t7rsmnmE99Jxf0SKFj3Ojyo/TOKMJSk bMfukDU9Agq/PFAE/+p4pxH6+s8B4DL9maxjDonNLIBzUktUH4EZY8HBrMQwICquJvHP BUSOz7qyWhbFsmyXT5tDJDAD4a15r3ncjozEAYRN+LGlbIQGsvLYkmVoO9XXeNSQC8tz 3EzjRvLbALPzsRTxxH+9fdaZ1zzxsB8B8emVDHTSZfMZd52dyG5jAi8gW6C/DDYzGgoO N9OQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712611484; x=1713216284; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QMpE4bJ02MY4VpUrTabgs0S4YJan2oEdqn4ZAnWdaHI=; b=K/fNEC6NNzL8H5A79rlz++vh1CggOxnSVKUK/NSZkk06Z76iO0/yzmuN00WwjfWAqU EM+7RWUpLrcbdL5+2bDU8CcD8oLJ29tfxjI2V+JY2mJNuJNOe78cpVOwkQyHlI2MDhYG VUpXcYFP4Bxhp+m41THHn1wHV18Z2fzbUZc+5MGM/ZV8n5OobwJxNGrUFEuu3HyQJWYK Dv430uAYBlDQJW/mt9raDKI8IpP0Of2obmOUfSBJdzunedpHceyxxmwXOrnLcgO67/OV /m4MFvY+aSfJ6dnk1ujT2mzTc1EEKWH8jQedfwED8kezFIFFJimPv4bvbrPfKi/w8SPU 1ojQ== X-Gm-Message-State: AOJu0YwSfIyj0Qac6cvhg5VY2RGqBsC0jEdCLplzqFZyQydxq2Yj+bbh nXpRej5jsyJ6/YlBgzVlyviC8LCt2XJYFhuc57fqdjH++/vvpvPh8z8LjjhHxhj20hGFbw9PDXQ 9Bhw= X-Google-Smtp-Source: AGHT+IHvoTGGI6wOHJW/vaZYZ5CPFT9VzK7qNr3hnScjrNr0W5+Pe1yQR6q8n+ImkYv82cT1fLXBNw== X-Received: by 2002:a05:6e02:1fe5:b0:36a:2cb9:127 with SMTP id dt5-20020a056e021fe500b0036a2cb90127mr1979064ilb.32.1712611484285; Mon, 08 Apr 2024 14:24:44 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id f16-20020a633810000000b005e43cce33f8sm6924725pga.88.2024.04.08.14.24.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Apr 2024 14:24:43 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v7 3/8] net/tap: validate and setup parameters for BPF RSS Date: Mon, 8 Apr 2024 14:18:34 -0700 Message-ID: <20240408212438.414099-4-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240408212438.414099-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240408212438.414099-1-stephen@networkplumber.org> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The flow RSS support via BPF was not using the key, or hash type parameters. Which is good because they were never properly setup. Fix the setup and validate the flow parameters, the BPF side gets fixed later. Signed-off-by: Stephen Hemminger --- drivers/net/tap/tap_flow.c | 65 +++++++++++++++++++++++++++++++++++--- drivers/net/tap/tap_rss.h | 5 ++- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c index 8fccd599f0..8cf64364a7 100644 --- a/drivers/net/tap/tap_flow.c +++ b/drivers/net/tap/tap_flow.c @@ -11,9 +11,11 @@ #include #include +#include #include #include #include + #include #include #include @@ -2061,6 +2063,21 @@ static int bpf_rss_key(enum bpf_rss_key_e cmd, __u32 *key_idx) return err; } + +/* Default RSS hash key also used by mlx devices */ +static const uint8_t rss_hash_default_key[] = { + 0x2c, 0xc6, 0x81, 0xd1, + 0x5b, 0xdb, 0xf4, 0xf7, + 0xfc, 0xa2, 0x83, 0x19, + 0xdb, 0x1a, 0x3e, 0x94, + 0x6b, 0x9e, 0x38, 0xd9, + 0x2c, 0x9c, 0x03, 0xd1, + 0xad, 0x99, 0x44, 0xa7, + 0xd9, 0x56, 0x3d, 0x59, + 0x06, 0x3c, 0x25, 0xf3, + 0xfc, 0x1f, 0xdc, 0x2a, +}; + /** * Add RSS hash calculations and queue selection * @@ -2079,11 +2096,11 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd, const struct rte_flow_action_rss *rss, struct rte_flow_error *error) { - /* 4096 is the maximum number of instructions for a BPF program */ + struct rss_key rss_entry = { }; + const uint8_t *key_in; + uint32_t hash_type = 0; unsigned int i; int err; - struct rss_key rss_entry = { .hash_fields = 0, - .key_size = 0 }; /* Check supported RSS features */ if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) @@ -2095,6 +2112,41 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd, (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "a nonzero RSS encapsulation level is not supported"); + if (rss->queue_num == 0 || rss->queue_num >= TAP_MAX_QUEUES) + return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "invalid number of queues"); + + /* allow RSS key_len 0 in case of NULL (default) RSS key. */ + if (rss->key_len == 0) { + if (rss->key != NULL) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION_CONF, + &rss->key_len, "RSS hash key length 0"); + key_in = rss_hash_default_key; + } else { + if (rss->key_len != TAP_RSS_HASH_KEY_SIZE) + return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "RSS hash invalid key length"); + if (rss->key == NULL) + return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "RSS hash key is NULL"); + key_in = rss->key; + } + + if (rss->types & TAP_RSS_HF_MASK) + return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "RSS hash type not supported"); + + if (rss->types & (RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_NONFRAG_IPV4_TCP)) + hash_type |= RTE_BIT32(HASH_FIELD_IPV4_L3_L4); + else if (rss->types & (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4)) + hash_type |= RTE_BIT32(HASH_FIELD_IPV4_L3); + + if (rss->types & (RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_NONFRAG_IPV6_TCP)) + hash_type |= RTE_BIT32(HASH_FIELD_IPV6_L3_L4); + else if (rss->types & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | RTE_ETH_RSS_IPV6_EX)) + hash_type |= RTE_BIT32(HASH_FIELD_IPV6_L3); + /* Get a new map key for a new RSS rule */ err = bpf_rss_key(KEY_CMD_GET, &flow->key_idx); if (err < 0) { @@ -2109,8 +2161,11 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd, rss_entry.nb_queues = rss->queue_num; for (i = 0; i < rss->queue_num; i++) rss_entry.queues[i] = rss->queue[i]; - rss_entry.hash_fields = - (1 << HASH_FIELD_IPV4_L3_L4) | (1 << HASH_FIELD_IPV6_L3_L4); + + rss_entry.hash_fields = hash_type; + rte_convert_rss_key((const uint32_t *)key_in, (uint32_t *)rss_entry.key, + TAP_RSS_HASH_KEY_SIZE); + /* Add this RSS entry to map */ err = tap_flow_bpf_update_rss_elem(pmd->map_fd, diff --git a/drivers/net/tap/tap_rss.h b/drivers/net/tap/tap_rss.h index 8766ffc244..6009be7031 100644 --- a/drivers/net/tap/tap_rss.h +++ b/drivers/net/tap/tap_rss.h @@ -24,11 +24,10 @@ enum hash_field { }; struct rss_key { - __u8 key[128]; __u32 hash_fields; - __u32 key_size; - __u32 queues[TAP_MAX_QUEUES]; + __u8 key[TAP_RSS_HASH_KEY_SIZE]; __u32 nb_queues; + __u32 queues[TAP_MAX_QUEUES]; } __attribute__((packed)); #endif /* _TAP_RSS_H_ */ From patchwork Mon Apr 8 21:18:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 139194 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0E77143DD2; Mon, 8 Apr 2024 23:25:14 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id DBB49406FF; Mon, 8 Apr 2024 23:24:49 +0200 (CEST) Received: from mail-pf1-f175.google.com (mail-pf1-f175.google.com [209.85.210.175]) by mails.dpdk.org (Postfix) with ESMTP id 3FADF4064C for ; Mon, 8 Apr 2024 23:24:46 +0200 (CEST) Received: by mail-pf1-f175.google.com with SMTP id d2e1a72fcca58-6ecf8ebff50so2944583b3a.1 for ; Mon, 08 Apr 2024 14:24:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712611485; x=1713216285; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=a2vMsT7lQuve1AwjvIanirgc6GLuVum0XUWRlqul+mc=; b=NcF1+m29AIfKciFaCxQppAGVDaAlXYtL3husMvpDI9zXUzm6v8bg6gUFnlBnHBnFjv 6R7IJD6jxXqI+W0RQhNrF/7IRtxMBy96veih8x3ExwYKCx0kyPVaQQoF0TOD6x3+2+lR 7dezVgQRQImf3cGvmrc7DzHMnJo3rrr5hfXxLSDLLzdcuMOYEHsXv37s4beBGzzimE5J OSmp1dfrrw4aFNHaSezGaCcvsHcyEPe7yEO62Yd2/S3MxwTfdp7Iexkxpj5aXmocwC4r KYE/KXC5RRceDGZMKTlGKiWt2gIDpXnvjbGYtxOTEOj55SUd5kiDczWkt800TlUK2rQs 1PsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712611485; x=1713216285; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=a2vMsT7lQuve1AwjvIanirgc6GLuVum0XUWRlqul+mc=; b=DB1EYIB6qN/TC6ZLpBVB60m7+Ue6bl43IVOG4LWGdXKom5ZUG/QeWYTkjCeSYWI11o tOq+h74vmkIlJnV2F/qrVueBUYRo63UElo0aeOGKm7YCwPqFsjTV998jXcV4DEqXu4AS I5ExN6275eqvFtoLMOXigdu0bSwV2Q6ee6OryDOyJY6xxspSmXTBKn3ezhA6tU8fivdj ZR5EoxR0ixIvw43du4m1ZofTVytL9R58VfOF3/S1mpBDY8m5AINBZHEFXnrPXW3Dx9Dd eHmLjdLUakL/2VpPQ/Bq5gxQDfok0ebvlHTtNtuUSaY9Y5mv+P5N46+J7c6ygDWGkuM+ sLhQ== X-Gm-Message-State: AOJu0YzkR+r2lNpFL8pCnXjffJO3raXebvvIadZCG0Jh8qfTC5opVjYC a/nqPYhD4YwW+z9GY0bDoCs81DIEhJHKGBIl3DetqpqxaBHXNYjihZVVoL2N47J3DlMu4reZjDg 074I= X-Google-Smtp-Source: AGHT+IH+2T5PulSw3AL9C8w9UDwz24yeUn+DRjLSu2ve/1yFc1KmI55GglPcqTx9oIw4u7hfLIDFSA== X-Received: by 2002:a05:6a20:9782:b0:1a7:52db:6711 with SMTP id hx2-20020a056a20978200b001a752db6711mr1114282pzc.2.1712611485129; Mon, 08 Apr 2024 14:24:45 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id f16-20020a633810000000b005e43cce33f8sm6924725pga.88.2024.04.08.14.24.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Apr 2024 14:24:44 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v7 4/8] net/tap: do not build flow support if header is out of date Date: Mon, 8 Apr 2024 14:18:35 -0700 Message-ID: <20240408212438.414099-5-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240408212438.414099-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240408212438.414099-1-stephen@networkplumber.org> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The proper place for finding bpf structures and functions is in linux/bpf.h. The original version was trying to workaround the case where the build environment was running on old pre BPF version of Glibc, but the target environment had BPF. Having own private (and divergent) version headers leads to future problems when BPF definitions evolve. If the build infrastructure is so old that TC flower is not supported, then the TAP device will build without any flow support. Signed-off-by: Stephen Hemminger --- drivers/net/tap/bpf/bpf_extract.py | 1 - drivers/net/tap/meson.build | 17 ++-- drivers/net/tap/rte_eth_tap.c | 38 +++++++-- drivers/net/tap/rte_eth_tap.h | 7 +- drivers/net/tap/tap_bpf.h | 121 ----------------------------- drivers/net/tap/tap_bpf_api.c | 20 +++-- drivers/net/tap/tap_bpf_insns.h | 2 - drivers/net/tap/tap_flow.c | 90 --------------------- 8 files changed, 60 insertions(+), 236 deletions(-) delete mode 100644 drivers/net/tap/tap_bpf.h diff --git a/drivers/net/tap/bpf/bpf_extract.py b/drivers/net/tap/bpf/bpf_extract.py index b630c42b80..73c4dafe4e 100644 --- a/drivers/net/tap/bpf/bpf_extract.py +++ b/drivers/net/tap/bpf/bpf_extract.py @@ -65,7 +65,6 @@ def write_header(out, source): print(f' * Auto-generated from {source}', file=out) print(" * This not the original source file. Do NOT edit it.", file=out) print(" */\n", file=out) - print("#include ", file=out) def main(): diff --git a/drivers/net/tap/meson.build b/drivers/net/tap/meson.build index 9cd124d53e..1fd20cfe93 100644 --- a/drivers/net/tap/meson.build +++ b/drivers/net/tap/meson.build @@ -7,13 +7,19 @@ if not is_linux endif sources = files( 'rte_eth_tap.c', - 'tap_bpf_api.c', - 'tap_flow.c', 'tap_intr.c', 'tap_netlink.c', - 'tap_tcmsgs.c', ) +if cc.has_header_symbol('linux/pkt_cls.h', 'TCA_FLOWER_ACT') + cflags += '-DHAVE_TCA_FLOWER' + sources += files( + 'tap_bpf_api.c', + 'tap_flow.c', + 'tap_tcmsgs.c', + ) +endif + deps = ['bus_vdev', 'gso', 'hash'] cflags += '-DTAP_MAX_QUEUES=8' @@ -23,12 +29,7 @@ cflags += '-DTAP_MAX_QUEUES=8' # "enum/define", "symbol to search" ] # args = [ - [ 'HAVE_TC_FLOWER', 'linux/pkt_cls.h', 'TCA_FLOWER_UNSPEC' ], - [ 'HAVE_TC_VLAN_ID', 'linux/pkt_cls.h', 'TCA_FLOWER_KEY_VLAN_PRIO' ], - [ 'HAVE_TC_BPF', 'linux/pkt_cls.h', 'TCA_BPF_UNSPEC' ], - [ 'HAVE_TC_BPF_FD', 'linux/pkt_cls.h', 'TCA_BPF_FD' ], [ 'HAVE_TC_ACT_BPF', 'linux/tc_act/tc_bpf.h', 'TCA_ACT_BPF_UNSPEC' ], - [ 'HAVE_TC_ACT_BPF_FD', 'linux/tc_act/tc_bpf.h', 'TCA_ACT_BPF_FD' ], ] config = configuration_data() foreach arg:args diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 38a1b2d825..3f4fe95a09 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -1124,12 +1124,15 @@ tap_dev_close(struct rte_eth_dev *dev) if (!internals->persist) tap_link_set_down(dev); + +#ifdef HAVE_TCA_FLOWER if (internals->nlsk_fd != -1) { tap_flow_flush(dev, NULL); tap_flow_implicit_flush(internals, NULL); tap_nl_final(internals->nlsk_fd); internals->nlsk_fd = -1; } +#endif for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) { struct rx_queue *rxq = &internals->rxq[i]; @@ -1265,6 +1268,7 @@ tap_promisc_enable(struct rte_eth_dev *dev) if (ret != 0) return ret; +#ifdef HAVE_TCA_FLOWER if (pmd->remote_if_index && !pmd->flow_isolate) { dev->data->promiscuous = 1; ret = tap_flow_implicit_create(pmd, TAP_REMOTE_PROMISC); @@ -1278,7 +1282,7 @@ tap_promisc_enable(struct rte_eth_dev *dev) return ret; } } - +#endif return 0; } @@ -1293,6 +1297,7 @@ tap_promisc_disable(struct rte_eth_dev *dev) if (ret != 0) return ret; +#ifdef HAVE_TCA_FLOWER if (pmd->remote_if_index && !pmd->flow_isolate) { dev->data->promiscuous = 0; ret = tap_flow_implicit_destroy(pmd, TAP_REMOTE_PROMISC); @@ -1306,6 +1311,7 @@ tap_promisc_disable(struct rte_eth_dev *dev) return ret; } } +#endif return 0; } @@ -1321,6 +1327,7 @@ tap_allmulti_enable(struct rte_eth_dev *dev) if (ret != 0) return ret; +#ifdef HAVE_TCA_FLOWER if (pmd->remote_if_index && !pmd->flow_isolate) { dev->data->all_multicast = 1; ret = tap_flow_implicit_create(pmd, TAP_REMOTE_ALLMULTI); @@ -1334,6 +1341,7 @@ tap_allmulti_enable(struct rte_eth_dev *dev) return ret; } } +#endif return 0; } @@ -1349,6 +1357,7 @@ tap_allmulti_disable(struct rte_eth_dev *dev) if (ret != 0) return ret; +#ifdef HAVE_TCA_FLOWER if (pmd->remote_if_index && !pmd->flow_isolate) { dev->data->all_multicast = 0; ret = tap_flow_implicit_destroy(pmd, TAP_REMOTE_ALLMULTI); @@ -1362,6 +1371,7 @@ tap_allmulti_disable(struct rte_eth_dev *dev) return ret; } } +#endif return 0; } @@ -1407,6 +1417,8 @@ tap_mac_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr) if (ret < 0) return ret; rte_memcpy(&pmd->eth_addr, mac_addr, RTE_ETHER_ADDR_LEN); + +#ifdef HAVE_TCA_FLOWER if (pmd->remote_if_index && !pmd->flow_isolate) { /* Replace MAC redirection rule after a MAC change */ ret = tap_flow_implicit_destroy(pmd, TAP_REMOTE_LOCAL_MAC); @@ -1424,6 +1436,7 @@ tap_mac_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr) return ret; } } +#endif return 0; } @@ -1901,7 +1914,9 @@ static const struct eth_dev_ops ops = { .stats_reset = tap_stats_reset, .dev_supported_ptypes_get = tap_dev_supported_ptypes_get, .rss_hash_update = tap_rss_hash_update, +#ifdef HAVE_TCA_FLOWER .flow_ops_get = tap_dev_flow_ops_get, +#endif }; static int @@ -1941,7 +1956,9 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, strlcpy(pmd->name, tap_name, sizeof(pmd->name)); pmd->type = type; pmd->ka_fd = -1; +#ifdef HAVE_TCA_FLOWER pmd->nlsk_fd = -1; +#endif pmd->gso_ctx_mp = NULL; pmd->ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); @@ -2021,6 +2038,14 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, /* Make network device persist after application exit */ pmd->persist = persist; + pmd->if_index = if_nametoindex(pmd->name); + if (!pmd->if_index) { + TAP_LOG(ERR, "%s: failed to get if_index.", pmd->name); + goto disable_rte_flow; + } + + +#ifdef HAVE_TCA_FLOWER /* * Set up everything related to rte_flow: * - netlink socket @@ -2035,11 +2060,6 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, pmd->name); goto disable_rte_flow; } - pmd->if_index = if_nametoindex(pmd->name); - if (!pmd->if_index) { - TAP_LOG(ERR, "%s: failed to get if_index.", pmd->name); - goto disable_rte_flow; - } if (qdisc_create_multiq(pmd->nlsk_fd, pmd->if_index) < 0) { TAP_LOG(ERR, "%s: failed to create multiq qdisc.", pmd->name); @@ -2050,6 +2070,7 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, pmd->name); goto disable_rte_flow; } + LIST_INIT(&pmd->flows); if (strlen(remote_iface)) { @@ -2102,6 +2123,7 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, goto error_remote; } } +#endif rte_eth_dev_probing_finish(dev); return 0; @@ -2116,14 +2138,18 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, rte_eth_dev_probing_finish(dev); return 0; +#ifdef HAVE_TCA_FLOWER error_remote: TAP_LOG(ERR, " Can't set up remote feature: %s(%d)", strerror(errno), errno); tap_flow_implicit_flush(pmd, NULL); +#endif error_exit: +#ifdef HAVE_TCA_FLOWER if (pmd->nlsk_fd != -1) close(pmd->nlsk_fd); +#endif if (pmd->ka_fd != -1) close(pmd->ka_fd); if (pmd->ioctl_sock != -1) diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h index 1bcf92ce80..af18b29090 100644 --- a/drivers/net/tap/rte_eth_tap.h +++ b/drivers/net/tap/rte_eth_tap.h @@ -16,6 +16,7 @@ #include #include #include + #include "tap_log.h" #ifdef IFF_MULTI_QUEUE @@ -70,15 +71,17 @@ struct pmd_internals { char remote_iface[RTE_ETH_NAME_MAX_LEN]; /* Remote netdevice name */ char name[RTE_ETH_NAME_MAX_LEN]; /* Internal Tap device name */ int type; /* Type field - TUN|TAP */ + int persist; /* 1 if keep link up, else 0 */ struct rte_ether_addr eth_addr; /* Mac address of the device port */ struct ifreq remote_initial_flags;/* Remote netdevice flags on init */ int remote_if_index; /* remote netdevice IF_INDEX */ int if_index; /* IF_INDEX for the port */ int ioctl_sock; /* socket for ioctl calls */ + +#ifdef HAVE_TCA_FLOWER int nlsk_fd; /* Netlink socket fd */ int flow_isolate; /* 1 if flow isolation is enabled */ int rss_enabled; /* 1 if RSS is enabled, else 0 */ - int persist; /* 1 if keep link up, else 0 */ /* implicit rules set when RSS is enabled */ int map_fd; /* BPF RSS map fd */ int bpf_fd[RTE_PMD_TAP_MAX_QUEUES];/* List of bpf fds per queue */ @@ -86,6 +89,8 @@ struct pmd_internals { LIST_HEAD(tap_flows, rte_flow) flows; /* rte_flow rules */ /* implicit rte_flow rules set when a remote device is active */ LIST_HEAD(tap_implicit_flows, rte_flow) implicit_flows; +#endif + struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES]; /* List of RX queues */ struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES]; /* List of TX queues */ struct rte_intr_handle *intr_handle; /* LSC interrupt handle. */ diff --git a/drivers/net/tap/tap_bpf.h b/drivers/net/tap/tap_bpf.h deleted file mode 100644 index 0d38bc111f..0000000000 --- a/drivers/net/tap/tap_bpf.h +++ /dev/null @@ -1,121 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 - * Copyright 2017 Mellanox Technologies, Ltd - */ - -#ifndef __TAP_BPF_H__ -#define __TAP_BPF_H__ - -#include - -/* Do not #include since eBPF must compile on different - * distros which may include partial definitions for eBPF (while the - * kernel itself may support eBPF). Instead define here all that is needed - */ - -/* BPF_MAP_UPDATE_ELEM command flags */ -#define BPF_ANY 0 /* create a new element or update an existing */ - -/* BPF architecture instruction struct */ -struct bpf_insn { - __u8 code; - __u8 dst_reg:4; - __u8 src_reg:4; - __s16 off; - __s32 imm; /* immediate value */ -}; - -/* BPF program types */ -enum bpf_prog_type { - BPF_PROG_TYPE_UNSPEC, - BPF_PROG_TYPE_SOCKET_FILTER, - BPF_PROG_TYPE_KPROBE, - BPF_PROG_TYPE_SCHED_CLS, - BPF_PROG_TYPE_SCHED_ACT, -}; - -/* BPF commands types */ -enum bpf_cmd { - BPF_MAP_CREATE, - BPF_MAP_LOOKUP_ELEM, - BPF_MAP_UPDATE_ELEM, - BPF_MAP_DELETE_ELEM, - BPF_MAP_GET_NEXT_KEY, - BPF_PROG_LOAD, -}; - -/* BPF maps types */ -enum bpf_map_type { - BPF_MAP_TYPE_UNSPEC, - BPF_MAP_TYPE_HASH, -}; - -/* union of anonymous structs used with TAP BPF commands */ -union bpf_attr { - /* BPF_MAP_CREATE command */ - struct { - __u32 map_type; - __u32 key_size; - __u32 value_size; - __u32 max_entries; - __u32 map_flags; - __u32 inner_map_fd; - }; - - /* BPF_MAP_UPDATE_ELEM, BPF_MAP_DELETE_ELEM commands */ - struct { - __u32 map_fd; - __aligned_u64 key; - union { - __aligned_u64 value; - __aligned_u64 next_key; - }; - __u64 flags; - }; - - /* BPF_PROG_LOAD command */ - struct { - __u32 prog_type; - __u32 insn_cnt; - __aligned_u64 insns; - __aligned_u64 license; - __u32 log_level; - __u32 log_size; - __aligned_u64 log_buf; - __u32 kern_version; - __u32 prog_flags; - }; -} __rte_aligned(8); - -#ifndef __NR_bpf -# if defined(__i386__) -# define __NR_bpf 357 -# elif defined(__x86_64__) -# define __NR_bpf 321 -# elif defined(__arm__) -# define __NR_bpf 386 -# elif defined(__aarch64__) -# define __NR_bpf 280 -# elif defined(__sparc__) -# define __NR_bpf 349 -# elif defined(__s390__) -# define __NR_bpf 351 -# elif defined(__powerpc__) -# define __NR_bpf 361 -# elif defined(__riscv) -# define __NR_bpf 280 -# elif defined(__loongarch__) -# define __NR_bpf 280 -# else -# error __NR_bpf not defined -# endif -#endif - -enum { - BPF_MAP_ID_KEY, - BPF_MAP_ID_SIMPLE, -}; - -static int bpf_load(enum bpf_prog_type type, const struct bpf_insn *insns, - size_t insns_cnt, const char *license); - -#endif /* __TAP_BPF_H__ */ diff --git a/drivers/net/tap/tap_bpf_api.c b/drivers/net/tap/tap_bpf_api.c index 15283f8917..9e05e2ddf1 100644 --- a/drivers/net/tap/tap_bpf_api.c +++ b/drivers/net/tap/tap_bpf_api.c @@ -2,19 +2,19 @@ * Copyright 2017 Mellanox Technologies, Ltd */ -#include -#include #include -#include +#include +#include -#include -#include #include #include -#include -#include + #include + +static int bpf_load(enum bpf_prog_type type, const struct bpf_insn *insns, + size_t insns_cnt, const char *license); + /** * Load BPF program (section cls_q) into the kernel and return a bpf fd * @@ -89,7 +89,13 @@ static inline __u64 ptr_to_u64(const void *ptr) static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, unsigned int size) { +#ifdef __NR_bpf return syscall(__NR_bpf, cmd, attr, size); +#else + TAP_LOG(ERR, "No bpf syscall, kernel headers too old?\n"); + errno = ENOSYS; + return -1; +#endif } /** diff --git a/drivers/net/tap/tap_bpf_insns.h b/drivers/net/tap/tap_bpf_insns.h index 53fa76c4e6..cdf2febf05 100644 --- a/drivers/net/tap/tap_bpf_insns.h +++ b/drivers/net/tap/tap_bpf_insns.h @@ -3,8 +3,6 @@ * This not the original source file. Do NOT edit it. */ -#include - static struct bpf_insn cls_q_insns[] = { {0x61, 2, 1, 52, 0x00000000}, {0x18, 3, 0, 0, 0xdeadbeef}, diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c index 8cf64364a7..5a5a4ea048 100644 --- a/drivers/net/tap/tap_flow.c +++ b/drivers/net/tap/tap_flow.c @@ -21,96 +21,6 @@ #include #include -#ifndef HAVE_TC_FLOWER -/* - * For kernels < 4.2, this enum is not defined. Runtime checks will be made to - * avoid sending TC messages the kernel cannot understand. - */ -enum { - TCA_FLOWER_UNSPEC, - TCA_FLOWER_CLASSID, - TCA_FLOWER_INDEV, - TCA_FLOWER_ACT, - TCA_FLOWER_KEY_ETH_DST, /* ETH_ALEN */ - TCA_FLOWER_KEY_ETH_DST_MASK, /* ETH_ALEN */ - TCA_FLOWER_KEY_ETH_SRC, /* ETH_ALEN */ - TCA_FLOWER_KEY_ETH_SRC_MASK, /* ETH_ALEN */ - TCA_FLOWER_KEY_ETH_TYPE, /* be16 */ - TCA_FLOWER_KEY_IP_PROTO, /* u8 */ - TCA_FLOWER_KEY_IPV4_SRC, /* be32 */ - TCA_FLOWER_KEY_IPV4_SRC_MASK, /* be32 */ - TCA_FLOWER_KEY_IPV4_DST, /* be32 */ - TCA_FLOWER_KEY_IPV4_DST_MASK, /* be32 */ - TCA_FLOWER_KEY_IPV6_SRC, /* struct in6_addr */ - TCA_FLOWER_KEY_IPV6_SRC_MASK, /* struct in6_addr */ - TCA_FLOWER_KEY_IPV6_DST, /* struct in6_addr */ - TCA_FLOWER_KEY_IPV6_DST_MASK, /* struct in6_addr */ - TCA_FLOWER_KEY_TCP_SRC, /* be16 */ - TCA_FLOWER_KEY_TCP_DST, /* be16 */ - TCA_FLOWER_KEY_UDP_SRC, /* be16 */ - TCA_FLOWER_KEY_UDP_DST, /* be16 */ -}; -#endif -#ifndef HAVE_TC_VLAN_ID -enum { - /* TCA_FLOWER_FLAGS, */ - TCA_FLOWER_KEY_VLAN_ID = TCA_FLOWER_KEY_UDP_DST + 2, /* be16 */ - TCA_FLOWER_KEY_VLAN_PRIO, /* u8 */ - TCA_FLOWER_KEY_VLAN_ETH_TYPE, /* be16 */ -}; -#endif -/* - * For kernels < 4.2 BPF related enums may not be defined. - * Runtime checks will be carried out to gracefully report on TC messages that - * are rejected by the kernel. Rejection reasons may be due to: - * 1. enum is not defined - * 2. enum is defined but kernel is not configured to support BPF system calls, - * BPF classifications or BPF actions. - */ -#ifndef HAVE_TC_BPF -enum { - TCA_BPF_UNSPEC, - TCA_BPF_ACT, - TCA_BPF_POLICE, - TCA_BPF_CLASSID, - TCA_BPF_OPS_LEN, - TCA_BPF_OPS, -}; -#endif -#ifndef HAVE_TC_BPF_FD -enum { - TCA_BPF_FD = TCA_BPF_OPS + 1, - TCA_BPF_NAME, -}; -#endif -#ifndef HAVE_TC_ACT_BPF -#define tc_gen \ - __u32 index; \ - __u32 capab; \ - int action; \ - int refcnt; \ - int bindcnt - -struct tc_act_bpf { - tc_gen; -}; - -enum { - TCA_ACT_BPF_UNSPEC, - TCA_ACT_BPF_TM, - TCA_ACT_BPF_PARMS, - TCA_ACT_BPF_OPS_LEN, - TCA_ACT_BPF_OPS, -}; - -#endif -#ifndef HAVE_TC_ACT_BPF_FD -enum { - TCA_ACT_BPF_FD = TCA_ACT_BPF_OPS + 1, - TCA_ACT_BPF_NAME, -}; -#endif - /* RSS key management */ enum bpf_rss_key_e { KEY_CMD_GET = 1, From patchwork Mon Apr 8 21:18:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 139195 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id A1D8643DD2; Mon, 8 Apr 2024 23:25:21 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3505340A6E; Mon, 8 Apr 2024 23:24:51 +0200 (CEST) Received: from mail-oo1-f42.google.com (mail-oo1-f42.google.com [209.85.161.42]) by mails.dpdk.org (Postfix) with ESMTP id 18D9240689 for ; Mon, 8 Apr 2024 23:24:47 +0200 (CEST) Received: by mail-oo1-f42.google.com with SMTP id 006d021491bc7-5aa20adda1dso1718006eaf.1 for ; Mon, 08 Apr 2024 14:24:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712611486; x=1713216286; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=38CZ4DWGHcOFCd2nCP00hPr47SsSpAChpDwZh8MAiuY=; b=TNH2taJ8Hft3F72jIpdNtn9tr4umaLEcuqHWyLCbGsqzb0f7Gh1how8w5PZBYji4JA ClNZt0PQM97J/Pb5nUKYePDirtywAh18P497ZIgDLENNtXXQr/uSezb43ZDM8ASNkDV5 IDWPIzVCYXk0Td5ou3e9bJMgywV3V/rlCyj+Tore2UMMkaT4VMVl9q1Bi/DH/z5tgg1X aNcRTNZ2KsKdpx9lK3HzKenH/yhHinGHiIbZuwQFZlfcZYtjUFa6OsqdgG/PqcK50pZe ggPFXifGOPU1W/V7/M1nu+OcPaefa/qIcPPi6WST2cA+4Cwd4s967pP52sjO2U7yo6hX pSGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712611486; x=1713216286; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=38CZ4DWGHcOFCd2nCP00hPr47SsSpAChpDwZh8MAiuY=; b=vluMXbM/xqBd3sXTVYiPhvvaqfREEGBkK6fsWzam4+YV+HPzyEGZh3MSHfBgVw2dvn OQgydU9gZp6i33VbGPcV4CDGzGTr5Cmbk6GcMdqT8j5Yjmb6xj8NS3Lfg9ool8hoWYr+ ifr1ukS5oJ7+I9B1j7ka27rINZvXfx06yezKVTEUPkYZ4d6m0tOPnS0j+zydkC2Nh0tl 4QudpAFb3P5/hbrlXXmZTKcNIbBQKh5JyxeLkZ7oEVk3Cm8SPlZ9kPMm3vRWzchTbxpU pPcwYqJdwzh4gUo6+pUqHmBbs3DZ8NjegQ3VifFAr5X4KTjI1P1X4LtuVJBxMDcLPtio b3wA== X-Gm-Message-State: AOJu0Yw619ZYHqwvg4OzCxBj607SU7Fw/mNbaqh/WCwp36yqikjYF5eB j4QN0liupsDtJ92puvIbqx7hhxTW93SCAct4rjb4CC9svDaUWn5bHJS8FRVEprBhBc91/ZrKRAE 85sg= X-Google-Smtp-Source: AGHT+IErbBTMLNC0ArI1bKnxAVUXmVfStJbovjbVr6RXu7Bxdw7Fl04m1Vs2Kr5wpBKvG2l8sNxpyw== X-Received: by 2002:a05:6358:4390:b0:17c:1da1:aa8f with SMTP id x16-20020a056358439000b0017c1da1aa8fmr10766881rwc.24.1712611486026; Mon, 08 Apr 2024 14:24:46 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id f16-20020a633810000000b005e43cce33f8sm6924725pga.88.2024.04.08.14.24.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Apr 2024 14:24:45 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v7 5/8] net/tap: rewrite the RSS BPF program Date: Mon, 8 Apr 2024 14:18:36 -0700 Message-ID: <20240408212438.414099-6-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240408212438.414099-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240408212438.414099-1-stephen@networkplumber.org> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Rewrite the BPF program used to do queue based RSS. Important changes: - uses newer BPF map format BTF - accepts key as parameter rather than constant default - can do L3 or L4 hashing - supports IPv4 options - supports IPv6 extension headers - restructured for readability The usage of BPF is different as well: - the incoming configuration is looked up based on class parameters rather than patching the BPF. - the resulting queue is placed in skb rather than requiring a second pass through classifier step. Note: This version only works with later patch to enable it on the DPDK driver side. It is submitted as an incremental patch to allow for easier review. Bisection still works because the old instruction are still present for now. Signed-off-by: Stephen Hemminger --- .gitignore | 3 - drivers/net/tap/bpf/Makefile | 19 -- drivers/net/tap/bpf/README | 38 ++++ drivers/net/tap/bpf/bpf_api.h | 276 -------------------------- drivers/net/tap/bpf/bpf_elf.h | 53 ----- drivers/net/tap/bpf/bpf_extract.py | 85 -------- drivers/net/tap/bpf/meson.build | 81 ++++++++ drivers/net/tap/bpf/tap_bpf_program.c | 255 ------------------------ drivers/net/tap/bpf/tap_rss.c | 264 ++++++++++++++++++++++++ 9 files changed, 383 insertions(+), 691 deletions(-) delete mode 100644 drivers/net/tap/bpf/Makefile create mode 100644 drivers/net/tap/bpf/README delete mode 100644 drivers/net/tap/bpf/bpf_api.h delete mode 100644 drivers/net/tap/bpf/bpf_elf.h delete mode 100644 drivers/net/tap/bpf/bpf_extract.py create mode 100644 drivers/net/tap/bpf/meson.build delete mode 100644 drivers/net/tap/bpf/tap_bpf_program.c create mode 100644 drivers/net/tap/bpf/tap_rss.c diff --git a/.gitignore b/.gitignore index 3f444dcace..01a47a7606 100644 --- a/.gitignore +++ b/.gitignore @@ -36,9 +36,6 @@ TAGS # ignore python bytecode files *.pyc -# ignore BPF programs -drivers/net/tap/bpf/tap_bpf_program.o - # DTS results dts/output diff --git a/drivers/net/tap/bpf/Makefile b/drivers/net/tap/bpf/Makefile deleted file mode 100644 index 9efeeb1bc7..0000000000 --- a/drivers/net/tap/bpf/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# This file is not built as part of normal DPDK build. -# It is used to generate the eBPF code for TAP RSS. - -CLANG=clang -CLANG_OPTS=-O2 -TARGET=../tap_bpf_insns.h - -all: $(TARGET) - -clean: - rm tap_bpf_program.o $(TARGET) - -tap_bpf_program.o: tap_bpf_program.c - $(CLANG) $(CLANG_OPTS) -emit-llvm -c $< -o - | \ - llc -march=bpf -filetype=obj -o $@ - -$(TARGET): tap_bpf_program.o - python3 bpf_extract.py -stap_bpf_program.c -o $@ $< diff --git a/drivers/net/tap/bpf/README b/drivers/net/tap/bpf/README new file mode 100644 index 0000000000..1d421ff42c --- /dev/null +++ b/drivers/net/tap/bpf/README @@ -0,0 +1,38 @@ +This is the BPF program used to implement the RSS across queues flow action. +The program is loaded when first RSS flow rule is created and is never unloaded. + +Each flow rule creates a unique key (handle) and this is used as the key +for finding the RSS information for that flow rule. + +This version is built the BPF Compile Once — Run Everywhere (CO-RE) +framework and uses libbpf and bpftool. + +Limitations +----------- +- requires libbpf to run +- rebuilding the BPF requires Clang and bpftool. + Some older versions of Ubuntu do not have working bpftool package. + Need a version of Clang that can compile to BPF. +- only standard Toeplitz hash with standard 40 byte key is supported +- the number of flow rules using RSS is limited to 32 + +Building +-------- +During the DPDK build process the meson build file checks that +libbpf, bpftool, and clang are not available. If everything is +there then BPF RSS is enabled. + +1. Using clang to compile tap_rss.c the tap_rss.bpf.o file. + +2. Using bpftool generate a skeleton header file tap_rss.skel.h from tap_rss.bpf.o. + This skeleton header is an large byte array which contains the + BPF binary and wrappers to load and use it. + +3. The tap flow code then compiles that BPF byte array into the PMD object. + +4. When needed the BPF array is loaded by libbpf. + +References +---------- +BPF and XDP reference guide +https://docs.cilium.io/en/latest/bpf/progtypes/ diff --git a/drivers/net/tap/bpf/bpf_api.h b/drivers/net/tap/bpf/bpf_api.h deleted file mode 100644 index 4cd25fa593..0000000000 --- a/drivers/net/tap/bpf/bpf_api.h +++ /dev/null @@ -1,276 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ - -#ifndef __BPF_API__ -#define __BPF_API__ - -/* Note: - * - * This file can be included into eBPF kernel programs. It contains - * a couple of useful helper functions, map/section ABI (bpf_elf.h), - * misc macros and some eBPF specific LLVM built-ins. - */ - -#include - -#include -#include -#include - -#include - -#include "bpf_elf.h" - -/** libbpf pin type. */ -enum libbpf_pin_type { - LIBBPF_PIN_NONE, - /* PIN_BY_NAME: pin maps by name (in /sys/fs/bpf by default) */ - LIBBPF_PIN_BY_NAME, -}; - -/** Type helper macros. */ - -#define __uint(name, val) int (*name)[val] -#define __type(name, val) typeof(val) *name -#define __array(name, val) typeof(val) *name[] - -/** Misc macros. */ - -#ifndef __stringify -# define __stringify(X) #X -#endif - -#ifndef __maybe_unused -# define __maybe_unused __attribute__((__unused__)) -#endif - -#ifndef offsetof -# define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER) -#endif - -#ifndef likely -# define likely(X) __builtin_expect(!!(X), 1) -#endif - -#ifndef unlikely -# define unlikely(X) __builtin_expect(!!(X), 0) -#endif - -#ifndef htons -# define htons(X) __constant_htons((X)) -#endif - -#ifndef ntohs -# define ntohs(X) __constant_ntohs((X)) -#endif - -#ifndef htonl -# define htonl(X) __constant_htonl((X)) -#endif - -#ifndef ntohl -# define ntohl(X) __constant_ntohl((X)) -#endif - -#ifndef __inline__ -# define __inline__ __attribute__((always_inline)) -#endif - -/** Section helper macros. */ - -#ifndef __section -# define __section(NAME) \ - __attribute__((section(NAME), used)) -#endif - -#ifndef __section_tail -# define __section_tail(ID, KEY) \ - __section(__stringify(ID) "/" __stringify(KEY)) -#endif - -#ifndef __section_xdp_entry -# define __section_xdp_entry \ - __section(ELF_SECTION_PROG) -#endif - -#ifndef __section_cls_entry -# define __section_cls_entry \ - __section(ELF_SECTION_CLASSIFIER) -#endif - -#ifndef __section_act_entry -# define __section_act_entry \ - __section(ELF_SECTION_ACTION) -#endif - -#ifndef __section_lwt_entry -# define __section_lwt_entry \ - __section(ELF_SECTION_PROG) -#endif - -#ifndef __section_license -# define __section_license \ - __section(ELF_SECTION_LICENSE) -#endif - -#ifndef __section_maps -# define __section_maps \ - __section(ELF_SECTION_MAPS) -#endif - -/** Declaration helper macros. */ - -#ifndef BPF_LICENSE -# define BPF_LICENSE(NAME) \ - char ____license[] __section_license = NAME -#endif - -/** Classifier helper */ - -#ifndef BPF_H_DEFAULT -# define BPF_H_DEFAULT -1 -#endif - -/** BPF helper functions for tc. Individual flags are in linux/bpf.h */ - -#ifndef __BPF_FUNC -# define __BPF_FUNC(NAME, ...) \ - (* NAME)(__VA_ARGS__) __maybe_unused -#endif - -#ifndef BPF_FUNC -# define BPF_FUNC(NAME, ...) \ - __BPF_FUNC(NAME, __VA_ARGS__) = (void *) BPF_FUNC_##NAME -#endif - -/* Map access/manipulation */ -static void *BPF_FUNC(map_lookup_elem, void *map, const void *key); -static int BPF_FUNC(map_update_elem, void *map, const void *key, - const void *value, uint32_t flags); -static int BPF_FUNC(map_delete_elem, void *map, const void *key); - -/* Time access */ -static uint64_t BPF_FUNC(ktime_get_ns); - -/* Debugging */ - -/* FIXME: __attribute__ ((format(printf, 1, 3))) not possible unless - * llvm bug https://llvm.org/bugs/show_bug.cgi?id=26243 gets resolved. - * It would require ____fmt to be made const, which generates a reloc - * entry (non-map). - */ -static void BPF_FUNC(trace_printk, const char *fmt, int fmt_size, ...); - -#ifndef printt -# define printt(fmt, ...) \ - __extension__ ({ \ - char ____fmt[] = fmt; \ - trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__); \ - }) -#endif - -/* Random numbers */ -static uint32_t BPF_FUNC(get_prandom_u32); - -/* Tail calls */ -static void BPF_FUNC(tail_call, struct __sk_buff *skb, void *map, - uint32_t index); - -/* System helpers */ -static uint32_t BPF_FUNC(get_smp_processor_id); -static uint32_t BPF_FUNC(get_numa_node_id); - -/* Packet misc meta data */ -static uint32_t BPF_FUNC(get_cgroup_classid, struct __sk_buff *skb); -static int BPF_FUNC(skb_under_cgroup, void *map, uint32_t index); - -static uint32_t BPF_FUNC(get_route_realm, struct __sk_buff *skb); -static uint32_t BPF_FUNC(get_hash_recalc, struct __sk_buff *skb); -static uint32_t BPF_FUNC(set_hash_invalid, struct __sk_buff *skb); - -/* Packet redirection */ -static int BPF_FUNC(redirect, int ifindex, uint32_t flags); -static int BPF_FUNC(clone_redirect, struct __sk_buff *skb, int ifindex, - uint32_t flags); - -/* Packet manipulation */ -static int BPF_FUNC(skb_load_bytes, struct __sk_buff *skb, uint32_t off, - void *to, uint32_t len); -static int BPF_FUNC(skb_store_bytes, struct __sk_buff *skb, uint32_t off, - const void *from, uint32_t len, uint32_t flags); - -static int BPF_FUNC(l3_csum_replace, struct __sk_buff *skb, uint32_t off, - uint32_t from, uint32_t to, uint32_t flags); -static int BPF_FUNC(l4_csum_replace, struct __sk_buff *skb, uint32_t off, - uint32_t from, uint32_t to, uint32_t flags); -static int BPF_FUNC(csum_diff, const void *from, uint32_t from_size, - const void *to, uint32_t to_size, uint32_t seed); -static int BPF_FUNC(csum_update, struct __sk_buff *skb, uint32_t wsum); - -static int BPF_FUNC(skb_change_type, struct __sk_buff *skb, uint32_t type); -static int BPF_FUNC(skb_change_proto, struct __sk_buff *skb, uint32_t proto, - uint32_t flags); -static int BPF_FUNC(skb_change_tail, struct __sk_buff *skb, uint32_t nlen, - uint32_t flags); - -static int BPF_FUNC(skb_pull_data, struct __sk_buff *skb, uint32_t len); - -/* Event notification */ -static int __BPF_FUNC(skb_event_output, struct __sk_buff *skb, void *map, - uint64_t index, const void *data, uint32_t size) = - (void *) BPF_FUNC_perf_event_output; - -/* Packet vlan encap/decap */ -static int BPF_FUNC(skb_vlan_push, struct __sk_buff *skb, uint16_t proto, - uint16_t vlan_tci); -static int BPF_FUNC(skb_vlan_pop, struct __sk_buff *skb); - -/* Packet tunnel encap/decap */ -static int BPF_FUNC(skb_get_tunnel_key, struct __sk_buff *skb, - struct bpf_tunnel_key *to, uint32_t size, uint32_t flags); -static int BPF_FUNC(skb_set_tunnel_key, struct __sk_buff *skb, - const struct bpf_tunnel_key *from, uint32_t size, - uint32_t flags); - -static int BPF_FUNC(skb_get_tunnel_opt, struct __sk_buff *skb, - void *to, uint32_t size); -static int BPF_FUNC(skb_set_tunnel_opt, struct __sk_buff *skb, - const void *from, uint32_t size); - -/** LLVM built-ins, mem*() routines work for constant size */ - -#ifndef lock_xadd -# define lock_xadd(ptr, val) ((void) __sync_fetch_and_add(ptr, val)) -#endif - -#ifndef memset -# define memset(s, c, n) __builtin_memset((s), (c), (n)) -#endif - -#ifndef memcpy -# define memcpy(d, s, n) __builtin_memcpy((d), (s), (n)) -#endif - -#ifndef memmove -# define memmove(d, s, n) __builtin_memmove((d), (s), (n)) -#endif - -/* FIXME: __builtin_memcmp() is not yet fully usable unless llvm bug - * https://llvm.org/bugs/show_bug.cgi?id=26218 gets resolved. Also - * this one would generate a reloc entry (non-map), otherwise. - */ -#if 0 -#ifndef memcmp -# define memcmp(a, b, n) __builtin_memcmp((a), (b), (n)) -#endif -#endif - -unsigned long long load_byte(void *skb, unsigned long long off) - asm ("llvm.bpf.load.byte"); - -unsigned long long load_half(void *skb, unsigned long long off) - asm ("llvm.bpf.load.half"); - -unsigned long long load_word(void *skb, unsigned long long off) - asm ("llvm.bpf.load.word"); - -#endif /* __BPF_API__ */ diff --git a/drivers/net/tap/bpf/bpf_elf.h b/drivers/net/tap/bpf/bpf_elf.h deleted file mode 100644 index ea8a11c95c..0000000000 --- a/drivers/net/tap/bpf/bpf_elf.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ -#ifndef __BPF_ELF__ -#define __BPF_ELF__ - -#include - -/* Note: - * - * Below ELF section names and bpf_elf_map structure definition - * are not (!) kernel ABI. It's rather a "contract" between the - * application and the BPF loader in tc. For compatibility, the - * section names should stay as-is. Introduction of aliases, if - * needed, are a possibility, though. - */ - -/* ELF section names, etc */ -#define ELF_SECTION_LICENSE "license" -#define ELF_SECTION_MAPS "maps" -#define ELF_SECTION_PROG "prog" -#define ELF_SECTION_CLASSIFIER "classifier" -#define ELF_SECTION_ACTION "action" - -#define ELF_MAX_MAPS 64 -#define ELF_MAX_LICENSE_LEN 128 - -/* Object pinning settings */ -#define PIN_NONE 0 -#define PIN_OBJECT_NS 1 -#define PIN_GLOBAL_NS 2 - -/* ELF map definition */ -struct bpf_elf_map { - __u32 type; - __u32 size_key; - __u32 size_value; - __u32 max_elem; - __u32 flags; - __u32 id; - __u32 pinning; - __u32 inner_id; - __u32 inner_idx; -}; - -#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \ - struct ____btf_map_##name { \ - type_key key; \ - type_val value; \ - }; \ - struct ____btf_map_##name \ - __attribute__ ((section(".maps." #name), used)) \ - ____btf_map_##name = { } - -#endif /* __BPF_ELF__ */ diff --git a/drivers/net/tap/bpf/bpf_extract.py b/drivers/net/tap/bpf/bpf_extract.py deleted file mode 100644 index 73c4dafe4e..0000000000 --- a/drivers/net/tap/bpf/bpf_extract.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python3 -# SPDX-License-Identifier: BSD-3-Clause -# Copyright (c) 2023 Stephen Hemminger - -import argparse -import sys -import struct -from tempfile import TemporaryFile -from elftools.elf.elffile import ELFFile - - -def load_sections(elffile): - """Get sections of interest from ELF""" - result = [] - parts = [("cls_q", "cls_q_insns"), ("l3_l4", "l3_l4_hash_insns")] - for name, tag in parts: - section = elffile.get_section_by_name(name) - if section: - insns = struct.iter_unpack('> 4 - dst = bpf[1] & 0xf - off = bpf[2] - imm = bpf[3] - print(f'\t{{{code:#04x}, {dst:4d}, {src:4d}, {off:8d}, {imm:#010x}}},', - file=out) - print('};', file=out) - - -def parse_args(): - """Parse command line arguments""" - parser = argparse.ArgumentParser() - parser.add_argument('-s', - '--source', - type=str, - help="original source file") - parser.add_argument('-o', '--out', type=str, help="output C file path") - parser.add_argument("file", - nargs='+', - help="object file path or '-' for stdin") - return parser.parse_args() - - -def open_input(path): - """Open the file or stdin""" - if path == "-": - temp = TemporaryFile() - temp.write(sys.stdin.buffer.read()) - return temp - return open(path, 'rb') - - -def write_header(out, source): - """Write file intro header""" - print("/* SPDX-License-Identifier: BSD-3-Clause", file=out) - if source: - print(f' * Auto-generated from {source}', file=out) - print(" * This not the original source file. Do NOT edit it.", file=out) - print(" */\n", file=out) - - -def main(): - '''program main function''' - args = parse_args() - - with open(args.out, 'w', - encoding="utf-8") if args.out else sys.stdout as out: - write_header(out, args.source) - for path in args.file: - elffile = ELFFile(open_input(path)) - sections = load_sections(elffile) - for name, insns in sections: - dump_section(name, insns, out) - - -if __name__ == "__main__": - main() diff --git a/drivers/net/tap/bpf/meson.build b/drivers/net/tap/bpf/meson.build new file mode 100644 index 0000000000..f2c03a19fd --- /dev/null +++ b/drivers/net/tap/bpf/meson.build @@ -0,0 +1,81 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2024 Stephen Hemminger + +enable_tap_rss = false + +libbpf = dependency('libbpf', required: false, method: 'pkg-config') +if not libbpf.found() + message('net/tap: no RSS support missing libbpf') + subdir_done() +endif + +# Debian install this in /usr/sbin which is not in $PATH +bpftool = find_program('bpftool', '/usr/sbin/bpftool', required: false, version: '>= 5.6.0') +if not bpftool.found() + message('net/tap: no RSS support missing bpftool') + subdir_done() +endif + +clang_supports_bpf = false +clang = find_program('clang', required: false) +if clang.found() + clang_supports_bpf = run_command(clang, '-target', 'bpf', '--print-supported-cpus', + check: false).returncode() == 0 +endif + +if not clang_supports_bpf + message('net/tap: no RSS support missing clang BPF') + subdir_done() +endif + +enable_tap_rss = true + +libbpf_include_dir = libbpf.get_variable(pkgconfig : 'includedir') + +# The include files and others include +# but is not defined for multi-lib environment target. +# Workaround by using include directoriy from the host build environment. +machine_name = run_command('uname', '-m').stdout().strip() +march_include_dir = '/usr/include/' + machine_name + '-linux-gnu' + +clang_flags = [ + '-O2', + '-Wall', + '-Wextra', + '-target', + 'bpf', + '-g', + '-c', +] + +bpf_o_cmd = [ + clang, + clang_flags, + '-idirafter', + libbpf_include_dir, + '-idirafter', + march_include_dir, + '@INPUT@', + '-o', + '@OUTPUT@' +] + +skel_h_cmd = [ + bpftool, + 'gen', + 'skeleton', + '@INPUT@' +] + +tap_rss_o = custom_target( + 'tap_rss.bpf.o', + input: 'tap_rss.c', + output: 'tap_rss.o', + command: bpf_o_cmd) + +tap_rss_skel_h = custom_target( + 'tap_rss.skel.h', + input: tap_rss_o, + output: 'tap_rss.skel.h', + command: skel_h_cmd, + capture: true) diff --git a/drivers/net/tap/bpf/tap_bpf_program.c b/drivers/net/tap/bpf/tap_bpf_program.c deleted file mode 100644 index f05aed021c..0000000000 --- a/drivers/net/tap/bpf/tap_bpf_program.c +++ /dev/null @@ -1,255 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 - * Copyright 2017 Mellanox Technologies, Ltd - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bpf_api.h" -#include "bpf_elf.h" -#include "../tap_rss.h" - -/** Create IPv4 address */ -#define IPv4(a, b, c, d) ((__u32)(((a) & 0xff) << 24) | \ - (((b) & 0xff) << 16) | \ - (((c) & 0xff) << 8) | \ - ((d) & 0xff)) - -#define PORT(a, b) ((__u16)(((a) & 0xff) << 8) | \ - ((b) & 0xff)) - -/* - * The queue number is offset by a unique QUEUE_OFFSET, to distinguish - * packets that have gone through this rule (skb->cb[1] != 0) from others. - */ -#define QUEUE_OFFSET 0x7cafe800 -#define PIN_GLOBAL_NS 2 - -#define KEY_IDX 0 -#define BPF_MAP_ID_KEY 1 - -struct vlan_hdr { - __be16 proto; - __be16 tci; -}; - -struct bpf_elf_map __attribute__((section("maps"), used)) -map_keys = { - .type = BPF_MAP_TYPE_HASH, - .id = BPF_MAP_ID_KEY, - .size_key = sizeof(__u32), - .size_value = sizeof(struct rss_key), - .max_elem = 256, - .pinning = PIN_GLOBAL_NS, -}; - -__section("cls_q") int -match_q(struct __sk_buff *skb) -{ - __u32 queue = skb->cb[1]; - /* queue is set by tap_flow_bpf_cls_q() before load */ - volatile __u32 q = 0xdeadbeef; - __u32 match_queue = QUEUE_OFFSET + q; - - /* printt("match_q$i() queue = %d\n", queue); */ - - if (queue != match_queue) - return TC_ACT_OK; - - /* queue match */ - skb->cb[1] = 0; - return TC_ACT_UNSPEC; -} - - -struct ipv4_l3_l4_tuple { - __u32 src_addr; - __u32 dst_addr; - __u16 dport; - __u16 sport; -} __attribute__((packed)); - -struct ipv6_l3_l4_tuple { - __u8 src_addr[16]; - __u8 dst_addr[16]; - __u16 dport; - __u16 sport; -} __attribute__((packed)); - -static const __u8 def_rss_key[TAP_RSS_HASH_KEY_SIZE] = { - 0xd1, 0x81, 0xc6, 0x2c, - 0xf7, 0xf4, 0xdb, 0x5b, - 0x19, 0x83, 0xa2, 0xfc, - 0x94, 0x3e, 0x1a, 0xdb, - 0xd9, 0x38, 0x9e, 0x6b, - 0xd1, 0x03, 0x9c, 0x2c, - 0xa7, 0x44, 0x99, 0xad, - 0x59, 0x3d, 0x56, 0xd9, - 0xf3, 0x25, 0x3c, 0x06, - 0x2a, 0xdc, 0x1f, 0xfc, -}; - -static __u32 __attribute__((always_inline)) -rte_softrss_be(const __u32 *input_tuple, const uint8_t *rss_key, - __u8 input_len) -{ - __u32 i, j, hash = 0; -#pragma unroll - for (j = 0; j < input_len; j++) { -#pragma unroll - for (i = 0; i < 32; i++) { - if (input_tuple[j] & (1U << (31 - i))) { - hash ^= ((const __u32 *)def_rss_key)[j] << i | - (__u32)((uint64_t) - (((const __u32 *)def_rss_key)[j + 1]) - >> (32 - i)); - } - } - } - return hash; -} - -static int __attribute__((always_inline)) -rss_l3_l4(struct __sk_buff *skb) -{ - void *data_end = (void *)(long)skb->data_end; - void *data = (void *)(long)skb->data; - __u16 proto = (__u16)skb->protocol; - __u32 key_idx = 0xdeadbeef; - __u32 hash; - struct rss_key *rsskey; - __u64 off = ETH_HLEN; - int j; - __u8 *key = 0; - __u32 len; - __u32 queue = 0; - bool mf = 0; - __u16 frag_off = 0; - - rsskey = map_lookup_elem(&map_keys, &key_idx); - if (!rsskey) { - printt("hash(): rss key is not configured\n"); - return TC_ACT_OK; - } - key = (__u8 *)rsskey->key; - - /* Get correct proto for 802.1ad */ - if (skb->vlan_present && skb->vlan_proto == htons(ETH_P_8021AD)) { - if (data + ETH_ALEN * 2 + sizeof(struct vlan_hdr) + - sizeof(proto) > data_end) - return TC_ACT_OK; - proto = *(__u16 *)(data + ETH_ALEN * 2 + - sizeof(struct vlan_hdr)); - off += sizeof(struct vlan_hdr); - } - - if (proto == htons(ETH_P_IP)) { - if (data + off + sizeof(struct iphdr) + sizeof(__u32) - > data_end) - return TC_ACT_OK; - - __u8 *src_dst_addr = data + off + offsetof(struct iphdr, saddr); - __u8 *frag_off_addr = data + off + offsetof(struct iphdr, frag_off); - __u8 *prot_addr = data + off + offsetof(struct iphdr, protocol); - __u8 *src_dst_port = data + off + sizeof(struct iphdr); - struct ipv4_l3_l4_tuple v4_tuple = { - .src_addr = IPv4(*(src_dst_addr + 0), - *(src_dst_addr + 1), - *(src_dst_addr + 2), - *(src_dst_addr + 3)), - .dst_addr = IPv4(*(src_dst_addr + 4), - *(src_dst_addr + 5), - *(src_dst_addr + 6), - *(src_dst_addr + 7)), - .sport = 0, - .dport = 0, - }; - /** Fetch the L4-payer port numbers only in-case of TCP/UDP - ** and also if the packet is not fragmented. Since fragmented - ** chunks do not have L4 TCP/UDP header. - **/ - if (*prot_addr == IPPROTO_UDP || *prot_addr == IPPROTO_TCP) { - frag_off = PORT(*(frag_off_addr + 0), - *(frag_off_addr + 1)); - mf = frag_off & 0x2000; - frag_off = frag_off & 0x1fff; - if (mf == 0 && frag_off == 0) { - v4_tuple.sport = PORT(*(src_dst_port + 0), - *(src_dst_port + 1)); - v4_tuple.dport = PORT(*(src_dst_port + 2), - *(src_dst_port + 3)); - } - } - __u8 input_len = sizeof(v4_tuple) / sizeof(__u32); - if (rsskey->hash_fields & (1 << HASH_FIELD_IPV4_L3)) - input_len--; - hash = rte_softrss_be((__u32 *)&v4_tuple, key, 3); - } else if (proto == htons(ETH_P_IPV6)) { - if (data + off + sizeof(struct ipv6hdr) + - sizeof(__u32) > data_end) - return TC_ACT_OK; - __u8 *src_dst_addr = data + off + - offsetof(struct ipv6hdr, saddr); - __u8 *src_dst_port = data + off + - sizeof(struct ipv6hdr); - __u8 *next_hdr = data + off + - offsetof(struct ipv6hdr, nexthdr); - - struct ipv6_l3_l4_tuple v6_tuple; - for (j = 0; j < 4; j++) - *((uint32_t *)&v6_tuple.src_addr + j) = - __builtin_bswap32(*((uint32_t *) - src_dst_addr + j)); - for (j = 0; j < 4; j++) - *((uint32_t *)&v6_tuple.dst_addr + j) = - __builtin_bswap32(*((uint32_t *) - src_dst_addr + 4 + j)); - - /** Fetch the L4 header port-numbers only if next-header - * is TCP/UDP **/ - if (*next_hdr == IPPROTO_UDP || *next_hdr == IPPROTO_TCP) { - v6_tuple.sport = PORT(*(src_dst_port + 0), - *(src_dst_port + 1)); - v6_tuple.dport = PORT(*(src_dst_port + 2), - *(src_dst_port + 3)); - } else { - v6_tuple.sport = 0; - v6_tuple.dport = 0; - } - - __u8 input_len = sizeof(v6_tuple) / sizeof(__u32); - if (rsskey->hash_fields & (1 << HASH_FIELD_IPV6_L3)) - input_len--; - hash = rte_softrss_be((__u32 *)&v6_tuple, key, 9); - } else { - return TC_ACT_PIPE; - } - - queue = rsskey->queues[(hash % rsskey->nb_queues) & - (TAP_MAX_QUEUES - 1)]; - skb->cb[1] = QUEUE_OFFSET + queue; - /* printt(">>>>> rss_l3_l4 hash=0x%x queue=%u\n", hash, queue); */ - - return TC_ACT_RECLASSIFY; -} - -#define RSS(L) \ - __section(#L) int \ - L ## _hash(struct __sk_buff *skb) \ - { \ - return rss_ ## L (skb); \ - } - -RSS(l3_l4) - -BPF_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/tap/bpf/tap_rss.c b/drivers/net/tap/bpf/tap_rss.c new file mode 100644 index 0000000000..888b3bdc24 --- /dev/null +++ b/drivers/net/tap/bpf/tap_rss.c @@ -0,0 +1,264 @@ +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 + * Copyright 2017 Mellanox Technologies, Ltd + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "../tap_rss.h" + +/* + * This map provides configuration information about flows which need BPF RSS. + * + * The hash is indexed by the skb mark. + */ +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(struct rss_key)); + __uint(max_entries, TAP_RSS_MAX); +} rss_map SEC(".maps"); + +#define IP_MF 0x2000 /** IP header Flags **/ +#define IP_OFFSET 0x1FFF /** IP header fragment offset **/ + +/* + * Compute Toeplitz hash over the input tuple. + * This is same as rte_softrss_be in lib/hash + * but loop needs to be setup to match BPF restrictions. + */ +static __u32 __attribute__((always_inline)) +softrss_be(const __u32 *input_tuple, __u32 input_len, const __u32 *key) +{ + __u32 i, j, hash = 0; + +#pragma unroll + for (j = 0; j < input_len; j++) { +#pragma unroll + for (i = 0; i < 32; i++) { + if (input_tuple[j] & (1U << (31 - i))) + hash ^= key[j] << i | key[j + 1] >> (32 - i); + } + } + return hash; +} + +/* + * Compute RSS hash for IPv4 packet. + * return in 0 if RSS not specified + */ +static __u32 __attribute__((always_inline)) +parse_ipv4(const struct __sk_buff *skb, __u32 hash_type, const __u32 *key) +{ + struct iphdr iph; + __u32 off = 0; + + if (bpf_skb_load_bytes_relative(skb, off, &iph, sizeof(iph), BPF_HDR_START_NET)) + return 0; /* no IP header present */ + + struct { + __u32 src_addr; + __u32 dst_addr; + __u16 dport; + __u16 sport; + } v4_tuple = { + .src_addr = bpf_ntohl(iph.saddr), + .dst_addr = bpf_ntohl(iph.daddr), + }; + + /* If only calculating L3 hash, do it now */ + if (hash_type & (1 << HASH_FIELD_IPV4_L3)) + return softrss_be((__u32 *)&v4_tuple, sizeof(v4_tuple) / sizeof(__u32) - 1, key); + + /* If packet is fragmented then no L4 hash is possible */ + if ((iph.frag_off & bpf_htons(IP_MF | IP_OFFSET)) != 0) + return 0; + + /* Do RSS on UDP or TCP protocols */ + if (iph.protocol == IPPROTO_UDP || iph.protocol == IPPROTO_TCP) { + __u16 src_dst_port[2]; + + off += iph.ihl * 4; + if (bpf_skb_load_bytes_relative(skb, off, &src_dst_port, sizeof(src_dst_port), + BPF_HDR_START_NET)) + return 0; /* TCP or UDP header missing */ + + v4_tuple.sport = bpf_ntohs(src_dst_port[0]); + v4_tuple.dport = bpf_ntohs(src_dst_port[1]); + return softrss_be((__u32 *)&v4_tuple, sizeof(v4_tuple) / sizeof(__u32), key); + } + + /* Other protocol */ + return 0; +} + +/* + * Parse Ipv6 extended headers, update offset and return next proto. + * returns next proto on success, -1 on malformed header + */ +static int __attribute__((always_inline)) +skip_ip6_ext(__u16 proto, const struct __sk_buff *skb, __u32 *off, int *frag) +{ + struct ext_hdr { + __u8 next_hdr; + __u8 len; + } xh; + unsigned int i; + + *frag = 0; + +#define MAX_EXT_HDRS 5 +#pragma unroll + for (i = 0; i < MAX_EXT_HDRS; i++) { + switch (proto) { + case IPPROTO_HOPOPTS: + case IPPROTO_ROUTING: + case IPPROTO_DSTOPTS: + if (bpf_skb_load_bytes_relative(skb, *off, &xh, sizeof(xh), + BPF_HDR_START_NET)) + return -1; + + *off += (xh.len + 1) * 8; + proto = xh.next_hdr; + break; + case IPPROTO_FRAGMENT: + if (bpf_skb_load_bytes_relative(skb, *off, &xh, sizeof(xh), + BPF_HDR_START_NET)) + return -1; + + *off += 8; + proto = xh.next_hdr; + *frag = 1; + return proto; /* this is always the last ext hdr */ + default: + return proto; + } + } + + /* too many extension headers give up */ + return -1; +} + +/* + * Compute RSS hash for IPv6 packet. + * return in 0 if RSS not specified + */ +static __u32 __attribute__((always_inline)) +parse_ipv6(const struct __sk_buff *skb, __u32 hash_type, const __u32 *key) +{ + struct { + __u32 src_addr[4]; + __u32 dst_addr[4]; + __u16 dport; + __u16 sport; + } v6_tuple = { }; + struct ipv6hdr ip6h; + __u32 off = 0, j; + int proto, frag; + + if (bpf_skb_load_bytes_relative(skb, off, &ip6h, sizeof(ip6h), BPF_HDR_START_NET)) + return 0; /* missing IPv6 header */ + +#pragma unroll + for (j = 0; j < 4; j++) { + v6_tuple.src_addr[j] = bpf_ntohl(ip6h.saddr.in6_u.u6_addr32[j]); + v6_tuple.dst_addr[j] = bpf_ntohl(ip6h.daddr.in6_u.u6_addr32[j]); + } + + /* If only doing L3 hash, do it now */ + if (hash_type & (1 << HASH_FIELD_IPV6_L3)) + return softrss_be((__u32 *)&v6_tuple, sizeof(v6_tuple) / sizeof(__u32) - 1, key); + + /* Skip extension headers if present */ + off += sizeof(ip6h); + proto = skip_ip6_ext(ip6h.nexthdr, skb, &off, &frag); + if (proto < 0) + return 0; + + /* If packet is a fragment then no L4 hash is possible */ + if (frag) + return 0; + + /* Do RSS on UDP or TCP */ + if (proto == IPPROTO_UDP || proto == IPPROTO_TCP) { + __u16 src_dst_port[2]; + + if (bpf_skb_load_bytes_relative(skb, off, &src_dst_port, sizeof(src_dst_port), + BPF_HDR_START_NET)) + return 0; + + v6_tuple.sport = bpf_ntohs(src_dst_port[0]); + v6_tuple.dport = bpf_ntohs(src_dst_port[1]); + + return softrss_be((__u32 *)&v6_tuple, sizeof(v6_tuple) / sizeof(__u32), key); + } + + return 0; +} + +/* + * Compute RSS hash for packets. + * Returns 0 if no hash is possible. + */ +static __u32 __attribute__((always_inline)) +calculate_rss_hash(const struct __sk_buff *skb, const struct rss_key *rsskey) +{ + const __u32 *key = (const __u32 *)rsskey->key; + + if (skb->protocol == bpf_htons(ETH_P_IP)) + return parse_ipv4(skb, rsskey->hash_fields, key); + else if (skb->protocol == bpf_htons(ETH_P_IPV6)) + return parse_ipv6(skb, rsskey->hash_fields, key); + else + return 0; +} + +/* + * Scale value to be into range [0, n) + * Assumes val is large (ie hash covers whole u32 range) + */ +static __u32 __attribute__((always_inline)) +reciprocal_scale(__u32 val, __u32 n) +{ + return (__u32)(((__u64)val * n) >> 32); +} + +/* + * When this BPF program is run by tc from the filter classifier, + * it is able to read skb metadata and packet data. + * + * For packets where RSS is not possible, then just return TC_ACT_OK. + * When RSS is desired, change the skb->queue_mapping and set TC_ACT_PIPE + * to continue processing. + * + * This should be BPF_PROG_TYPE_SCHED_ACT so section needs to be "action" + */ +SEC("action") int +rss_flow_action(struct __sk_buff *skb) +{ + const struct rss_key *rsskey; + __u32 mark = skb->mark; + __u32 hash; + + /* Lookup RSS configuration for that BPF class */ + rsskey = bpf_map_lookup_elem(&rss_map, &mark); + if (rsskey == NULL) + return TC_ACT_OK; + + hash = calculate_rss_hash(skb, rsskey); + if (!hash) + return TC_ACT_OK; + + /* Fold hash to the number of queues configured */ + skb->queue_mapping = reciprocal_scale(hash, rsskey->nb_queues); + return TC_ACT_PIPE; +} + +char _license[] SEC("license") = "Dual BSD/GPL"; From patchwork Mon Apr 8 21:18:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 139196 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 1318D43DD2; Mon, 8 Apr 2024 23:25:30 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 56D9840A72; Mon, 8 Apr 2024 23:24:52 +0200 (CEST) Received: from mail-pf1-f181.google.com (mail-pf1-f181.google.com [209.85.210.181]) by mails.dpdk.org (Postfix) with ESMTP id 0D80A40695 for ; Mon, 8 Apr 2024 23:24:48 +0200 (CEST) Received: by mail-pf1-f181.google.com with SMTP id d2e1a72fcca58-6ecfeefe94cso2338488b3a.0 for ; Mon, 08 Apr 2024 14:24:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712611487; x=1713216287; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7souVghfIaPrhMjgiE94xKGFDLDlY0XMcMp6IrsP03g=; b=tRgaOSE9By9kJM5szx10Btrynzsbq+ivo4WnCjtRCIOaAxP1siBrCN8UFKYLRRh5Pf RVQ/1RRICymK6413eVvgPpmLASok+br8rDmYa5Zc/DJWKDXYSLiFkD5KfFg5/irTt7G5 l4QCVQZNbZKzlFoeT2D1//X8lP0A/fFyYQaDWreUhd2r1uj6I5YOI6qk4PnfcVCwUn39 we9CK9CeAxUQ8oi243XjczhMAqLRbgAxaSzDkS1RuyNt31H9vgYP9YVFfBnmpW6GMQ92 epGwIgMgJ3c2mBs7IB6CiBw4nRsQF0XIuu8bco+3bCB4XqjMP63duHK4Cf06JCHpBoNW OXPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712611487; x=1713216287; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7souVghfIaPrhMjgiE94xKGFDLDlY0XMcMp6IrsP03g=; b=bsKVFK7PsLFVg2zxRppJ++40OIkMidwr/1OfEhkY7GzWKfYEKmRVq9yT6W2bqKiA6D nF40nG4tyUEZ7ZsSdXSPblJpa2nPrlPZ/IaLzZLSxhn1tnoS3OEN7k4QXK5yZ6O8DcRq 7yMD3hPEl19MNSqXzcUuljQTo3ZFTwX7xpXhAtPqPBielYX5ZJUancaqJLCukkCk+OSE zYb1vnBvsjkkEQTNONgaBIbokMd0Z4s9dLKU8mhmiEK4r+98h2FowxO7NiterWZXd9x0 740zETdQDJOsFerR0JcOSzLZ3pAXMMjN/Kwd9PFbLCyR+x03W1H8xn30+Q4ExY2oWLDS owXQ== X-Gm-Message-State: AOJu0YxSNTEZzRLT9BOo4MJ8MYGuwkflkeCCcF7bEf/MM5xZ/+TQmoef EfBgRklbuX0qbwDx6zSTQVtBfRlebzICSk6bM7F6gBBSFVRyTv2YLEPTWRaP4sUdZG07ZlB/NpM fMHM= X-Google-Smtp-Source: AGHT+IE2EQZ2HeFi2y7CcbVI9w1AGDLQC5BESLlD/EfPtbQFNWBhkyps3adj3VPQniT4LAcnW6a6MQ== X-Received: by 2002:a05:6a21:199:b0:1a7:7460:7e9a with SMTP id le25-20020a056a21019900b001a774607e9amr1410458pzb.9.1712611486991; Mon, 08 Apr 2024 14:24:46 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id f16-20020a633810000000b005e43cce33f8sm6924725pga.88.2024.04.08.14.24.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Apr 2024 14:24:46 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v7 6/8] net/tap: use libbpf to load new BPF program Date: Mon, 8 Apr 2024 14:18:37 -0700 Message-ID: <20240408212438.414099-7-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240408212438.414099-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240408212438.414099-1-stephen@networkplumber.org> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org There were multiple issues in the RSS queue support in the TAP driver. This required extensive rework of the BPF support. Change the BPF loading to use bpftool to create a skeleton header file, and load with libbpf. The BPF is always compiled from source so less chance that source and instructions diverge. Also resolves issue where libbpf and source get out of sync. The program is only loaded once, so if multiple rules are created only one BPF program is loaded in kernel. The new BPF program only needs a single action. No need for action and re-classification step. It also fixes the missing bits from the original. - supports setting RSS key per flow - level of hash can be L3 or L3/L4. Signed-off-by: Stephen Hemminger --- drivers/net/tap/bpf/meson.build | 34 ++- drivers/net/tap/bpf/tap_rss.c | 45 ++-- drivers/net/tap/meson.build | 35 ++- drivers/net/tap/rte_eth_tap.c | 14 +- drivers/net/tap/rte_eth_tap.h | 6 +- drivers/net/tap/tap_flow.c | 408 +++++++------------------------- drivers/net/tap/tap_flow.h | 17 +- drivers/net/tap/tap_rss.h | 10 +- drivers/net/tap/tap_tcmsgs.h | 4 +- 9 files changed, 179 insertions(+), 394 deletions(-) diff --git a/drivers/net/tap/bpf/meson.build b/drivers/net/tap/bpf/meson.build index f2c03a19fd..563e5d1f21 100644 --- a/drivers/net/tap/bpf/meson.build +++ b/drivers/net/tap/bpf/meson.build @@ -3,15 +3,26 @@ enable_tap_rss = false -libbpf = dependency('libbpf', required: false, method: 'pkg-config') +# Loading BPF requires libbpf +# and the bpf_map__XXX API's were introduced in 0.8.0 +libbpf = dependency('libbpf', version: '>= 1.0', + required: false, method: 'pkg-config') if not libbpf.found() message('net/tap: no RSS support missing libbpf') subdir_done() endif +# Making skeleton needs bpftool # Debian install this in /usr/sbin which is not in $PATH -bpftool = find_program('bpftool', '/usr/sbin/bpftool', required: false, version: '>= 5.6.0') -if not bpftool.found() +bpftool_supports_skel = false +bpftool = find_program('bpftool', '/usr/sbin/bpftool', required: false) +if bpftool.found() + # Some Ubuntu has non-functional bpftool + bpftool_supports_skel = run_command(bpftool, 'gen', 'help', + check:false).returncode() == 0 +endif + +if not bpftool_supports_skel message('net/tap: no RSS support missing bpftool') subdir_done() endif @@ -42,6 +53,7 @@ clang_flags = [ '-O2', '-Wall', '-Wextra', + max_queues, '-target', 'bpf', '-g', @@ -67,6 +79,22 @@ skel_h_cmd = [ '@INPUT@' ] +vmlinux_h_cmd = [ + bpftool, + 'btf', + 'dump', + 'file', + '/sys/kernel/btf/vmlinux', + 'format', + 'c' +] + +vmlinux_h = custom_target( + 'vmlinux.h', + output: 'vmlinux.h', + command: vmlinux_h_cmd, + capture: true) + tap_rss_o = custom_target( 'tap_rss.bpf.o', input: 'tap_rss.c', diff --git a/drivers/net/tap/bpf/tap_rss.c b/drivers/net/tap/bpf/tap_rss.c index 888b3bdc24..1d71941c53 100644 --- a/drivers/net/tap/bpf/tap_rss.c +++ b/drivers/net/tap/bpf/tap_rss.c @@ -203,23 +203,6 @@ parse_ipv6(const struct __sk_buff *skb, __u32 hash_type, const __u32 *key) return 0; } -/* - * Compute RSS hash for packets. - * Returns 0 if no hash is possible. - */ -static __u32 __attribute__((always_inline)) -calculate_rss_hash(const struct __sk_buff *skb, const struct rss_key *rsskey) -{ - const __u32 *key = (const __u32 *)rsskey->key; - - if (skb->protocol == bpf_htons(ETH_P_IP)) - return parse_ipv4(skb, rsskey->hash_fields, key); - else if (skb->protocol == bpf_htons(ETH_P_IPV6)) - return parse_ipv6(skb, rsskey->hash_fields, key); - else - return 0; -} - /* * Scale value to be into range [0, n) * Assumes val is large (ie hash covers whole u32 range) @@ -244,20 +227,40 @@ SEC("action") int rss_flow_action(struct __sk_buff *skb) { const struct rss_key *rsskey; - __u32 mark = skb->mark; + const __u32 *key; + __be16 proto; + __u32 mark; __u32 hash; + __u16 queue; + + __builtin_preserve_access_index(({ + mark = skb->mark; + proto = skb->protocol; + })); /* Lookup RSS configuration for that BPF class */ rsskey = bpf_map_lookup_elem(&rss_map, &mark); if (rsskey == NULL) return TC_ACT_OK; - hash = calculate_rss_hash(skb, rsskey); - if (!hash) + key = (const __u32 *)rsskey->key; + + if (proto == bpf_htons(ETH_P_IP)) + hash = parse_ipv4(skb, rsskey->hash_fields, key); + else if (proto == bpf_htons(ETH_P_IPV6)) + hash = parse_ipv6(skb, rsskey->hash_fields, key); + else + hash = 0; + + if (hash == 0) return TC_ACT_OK; /* Fold hash to the number of queues configured */ - skb->queue_mapping = reciprocal_scale(hash, rsskey->nb_queues); + queue = reciprocal_scale(hash, rsskey->nb_queues); + + __builtin_preserve_access_index(({ + skb->queue_mapping = queue; + })); return TC_ACT_PIPE; } diff --git a/drivers/net/tap/meson.build b/drivers/net/tap/meson.build index 1fd20cfe93..1871448a00 100644 --- a/drivers/net/tap/meson.build +++ b/drivers/net/tap/meson.build @@ -5,36 +5,31 @@ if not is_linux build = false reason = 'only supported on Linux' endif + sources = files( 'rte_eth_tap.c', 'tap_intr.c', 'tap_netlink.c', ) +deps = ['bus_vdev', 'gso', 'hash'] + +max_queues = '-DTAP_MAX_QUEUES=16' +cflags += max_queues + +require_iova_in_mbuf = false + if cc.has_header_symbol('linux/pkt_cls.h', 'TCA_FLOWER_ACT') cflags += '-DHAVE_TCA_FLOWER' sources += files( - 'tap_bpf_api.c', 'tap_flow.c', 'tap_tcmsgs.c', ) -endif -deps = ['bus_vdev', 'gso', 'hash'] - -cflags += '-DTAP_MAX_QUEUES=8' - -# input array for meson symbol search: -# [ "MACRO to define if found", "header for the search", -# "enum/define", "symbol to search" ] -# -args = [ - [ 'HAVE_TC_ACT_BPF', 'linux/tc_act/tc_bpf.h', 'TCA_ACT_BPF_UNSPEC' ], -] -config = configuration_data() -foreach arg:args - config.set(arg[0], cc.has_header_symbol(arg[1], arg[2])) -endforeach -configure_file(output : 'tap_autoconf.h', configuration : config) - -require_iova_in_mbuf = false + subdir('bpf') + if enable_tap_rss + cflags += '-DHAVE_BPF_RSS' + ext_deps += libbpf + sources += tap_rss_skel_h + endif +endif diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 3f4fe95a09..793730de08 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -1131,6 +1131,7 @@ tap_dev_close(struct rte_eth_dev *dev) tap_flow_implicit_flush(internals, NULL); tap_nl_final(internals->nlsk_fd); internals->nlsk_fd = -1; + tap_flow_bpf_destroy(internals); } #endif @@ -1956,6 +1957,7 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, strlcpy(pmd->name, tap_name, sizeof(pmd->name)); pmd->type = type; pmd->ka_fd = -1; + #ifdef HAVE_TCA_FLOWER pmd->nlsk_fd = -1; #endif @@ -2038,13 +2040,6 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, /* Make network device persist after application exit */ pmd->persist = persist; - pmd->if_index = if_nametoindex(pmd->name); - if (!pmd->if_index) { - TAP_LOG(ERR, "%s: failed to get if_index.", pmd->name); - goto disable_rte_flow; - } - - #ifdef HAVE_TCA_FLOWER /* * Set up everything related to rte_flow: @@ -2060,6 +2055,11 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, pmd->name); goto disable_rte_flow; } + pmd->if_index = if_nametoindex(pmd->name); + if (!pmd->if_index) { + TAP_LOG(ERR, "%s: failed to get if_index.", pmd->name); + goto disable_rte_flow; + } if (qdisc_create_multiq(pmd->nlsk_fd, pmd->if_index) < 0) { TAP_LOG(ERR, "%s: failed to create multiq qdisc.", pmd->name); diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h index af18b29090..ce4322ad04 100644 --- a/drivers/net/tap/rte_eth_tap.h +++ b/drivers/net/tap/rte_eth_tap.h @@ -81,10 +81,8 @@ struct pmd_internals { #ifdef HAVE_TCA_FLOWER int nlsk_fd; /* Netlink socket fd */ int flow_isolate; /* 1 if flow isolation is enabled */ - int rss_enabled; /* 1 if RSS is enabled, else 0 */ - /* implicit rules set when RSS is enabled */ - int map_fd; /* BPF RSS map fd */ - int bpf_fd[RTE_PMD_TAP_MAX_QUEUES];/* List of bpf fds per queue */ + + struct tap_rss *rss; /* BPF program */ LIST_HEAD(tap_flows, rte_flow) flows; /* rte_flow rules */ /* implicit rte_flow rules set when a remote device is active */ diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c index 5a5a4ea048..77dc8e9741 100644 --- a/drivers/net/tap/tap_flow.c +++ b/drivers/net/tap/tap_flow.c @@ -15,25 +15,19 @@ #include #include #include +#include #include -#include #include #include -/* RSS key management */ -enum bpf_rss_key_e { - KEY_CMD_GET = 1, - KEY_CMD_RELEASE, - KEY_CMD_INIT, - KEY_CMD_DEINIT, -}; - -enum key_status_e { - KEY_STAT_UNSPEC, - KEY_STAT_USED, - KEY_STAT_AVAILABLE, -}; +#ifdef HAVE_BPF_RSS +/* Workaround for warning in bpftool generated skeleton code */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#include "tap_rss.skel.h" +#pragma GCC diagnostic pop +#endif #define ISOLATE_HANDLE 1 #define REMOTE_PROMISCUOUS_HANDLE 2 @@ -41,8 +35,6 @@ enum key_status_e { struct rte_flow { LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure */ struct rte_flow *remote_flow; /* associated remote flow */ - int bpf_fd[SEC_MAX]; /* list of bfs fds per ELF section */ - uint32_t key_idx; /* RSS rule key index into BPF map */ struct nlmsg msg; }; @@ -69,9 +61,11 @@ struct action_data { struct skbedit { struct tc_skbedit skbedit; uint16_t queue; + uint32_t mark; } skbedit; struct bpf { struct tc_act_bpf bpf; + uint32_t map_key; int bpf_fd; const char *annotation; } bpf; @@ -112,13 +106,12 @@ tap_flow_isolate(struct rte_eth_dev *dev, int set, struct rte_flow_error *error); -static int bpf_rss_key(enum bpf_rss_key_e cmd, __u32 *key_idx); -static int rss_enable(struct pmd_internals *pmd, - const struct rte_flow_attr *attr, - struct rte_flow_error *error); +#ifdef HAVE_BPF_RSS +static int rss_enable(struct pmd_internals *pmd, struct rte_flow_error *error); static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd, const struct rte_flow_action_rss *rss, struct rte_flow_error *error); +#endif static const struct rte_flow_ops tap_flow_ops = { .validate = tap_flow_validate, @@ -853,10 +846,11 @@ add_action(struct rte_flow *flow, size_t *act_index, struct action_data *adata) &adata->mirred); } else if (strcmp("skbedit", adata->id) == 0) { tap_nlattr_add(&msg->nh, TCA_SKBEDIT_PARMS, - sizeof(adata->skbedit.skbedit), - &adata->skbedit.skbedit); - tap_nlattr_add16(&msg->nh, TCA_SKBEDIT_QUEUE_MAPPING, - adata->skbedit.queue); + sizeof(adata->skbedit.skbedit), &adata->skbedit.skbedit); + if (adata->skbedit.mark) + tap_nlattr_add32(&msg->nh, TCA_SKBEDIT_MARK, adata->skbedit.mark); + else + tap_nlattr_add16(&msg->nh, TCA_SKBEDIT_QUEUE_MAPPING, adata->skbedit.queue); } else if (strcmp("bpf", adata->id) == 0) { tap_nlattr_add32(&msg->nh, TCA_ACT_BPF_FD, adata->bpf.bpf_fd); tap_nlattr_add(&msg->nh, TCA_ACT_BPF_NAME, @@ -1104,8 +1098,7 @@ priv_flow_process(struct pmd_internals *pmd, }, }; - err = add_actions(flow, 1, &adata, - TCA_FLOWER_ACT); + err = add_actions(flow, 1, &adata, TCA_FLOWER_ACT); } } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) { const struct rte_flow_action_queue *queue = @@ -1135,6 +1128,7 @@ priv_flow_process(struct pmd_internals *pmd, err = add_actions(flow, 1, &adata, TCA_FLOWER_ACT); } +#ifdef HAVE_BPF_RSS } else if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) { const struct rte_flow_action_rss *rss = (const struct rte_flow_action_rss *) @@ -1143,13 +1137,14 @@ priv_flow_process(struct pmd_internals *pmd, if (action++) goto exit_action_not_supported; - if (!pmd->rss_enabled) { - err = rss_enable(pmd, attr, error); + if (pmd->rss == NULL) { + err = rss_enable(pmd, error); if (err) goto exit_return_error; } if (flow) err = rss_add_actions(flow, pmd, rss, error); +#endif } else { goto exit_action_not_supported; } @@ -1246,26 +1241,17 @@ tap_flow_set_handle(struct rte_flow *flow) * */ static void -tap_flow_free(struct pmd_internals *pmd, struct rte_flow *flow) +tap_flow_free(struct pmd_internals *pmd __rte_unused, struct rte_flow *flow) { - int i; - if (!flow) return; - if (pmd->rss_enabled) { - /* Close flow BPF file descriptors */ - for (i = 0; i < SEC_MAX; i++) - if (flow->bpf_fd[i] != 0) { - close(flow->bpf_fd[i]); - flow->bpf_fd[i] = 0; - } - - /* Release the map key for this RSS rule */ - bpf_rss_key(KEY_CMD_RELEASE, &flow->key_idx); - flow->key_idx = 0; - } - +#ifdef HAVE_BPF_RSS + struct tap_rss *rss = pmd->rss; + if (rss) + bpf_map__delete_elem(rss->maps.rss_map, + &flow->msg.t.tcm_handle, sizeof(uint32_t), 0); +#endif /* Free flow allocated memory */ rte_free(flow); } @@ -1733,14 +1719,18 @@ tap_flow_implicit_flush(struct pmd_internals *pmd, struct rte_flow_error *error) return 0; } -#define MAX_RSS_KEYS 256 -#define KEY_IDX_OFFSET (3 * MAX_RSS_KEYS) -#define SEC_NAME_CLS_Q "cls_q" - -static const char *sec_name[SEC_MAX] = { - [SEC_L3_L4] = "l3_l4", -}; +/** + * Cleanup when device is closed + */ +void tap_flow_bpf_destroy(struct pmd_internals *pmd __rte_unused) +{ +#ifdef HAVE_BPF_RSS + tap_rss__destroy(pmd->rss); + pmd->rss = NULL; +#endif +} +#ifdef HAVE_BPF_RSS /** * Enable RSS on tap: create TC rules for queuing. * @@ -1755,225 +1745,32 @@ static const char *sec_name[SEC_MAX] = { * * @return 0 on success, negative value on failure. */ -static int rss_enable(struct pmd_internals *pmd, - const struct rte_flow_attr *attr, - struct rte_flow_error *error) +static int rss_enable(struct pmd_internals *pmd, struct rte_flow_error *error) { - struct rte_flow *rss_flow = NULL; - struct nlmsg *msg = NULL; - /* 4096 is the maximum number of instructions for a BPF program */ - char annotation[64]; - int i; - int err = 0; - - /* unlimit locked memory */ - struct rlimit memlock_limit = { - .rlim_cur = RLIM_INFINITY, - .rlim_max = RLIM_INFINITY, - }; - setrlimit(RLIMIT_MEMLOCK, &memlock_limit); - - /* Get a new map key for a new RSS rule */ - err = bpf_rss_key(KEY_CMD_INIT, NULL); - if (err < 0) { - rte_flow_error_set( - error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, - "Failed to initialize BPF RSS keys"); - - return -1; - } - - /* - * Create BPF RSS MAP - */ - pmd->map_fd = tap_flow_bpf_rss_map_create(sizeof(__u32), /* key size */ - sizeof(struct rss_key), - MAX_RSS_KEYS); - if (pmd->map_fd < 0) { - TAP_LOG(ERR, - "Failed to create BPF map (%d): %s", - errno, strerror(errno)); - rte_flow_error_set( - error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, - "Kernel too old or not configured " - "to support BPF maps"); - - return -ENOTSUP; - } - - /* - * Add a rule per queue to match reclassified packets and direct them to - * the correct queue. - */ - for (i = 0; i < pmd->dev->data->nb_rx_queues; i++) { - pmd->bpf_fd[i] = tap_flow_bpf_cls_q(i); - if (pmd->bpf_fd[i] < 0) { - TAP_LOG(ERR, - "Failed to load BPF section %s for queue %d", - SEC_NAME_CLS_Q, i); - rte_flow_error_set( - error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, - NULL, - "Kernel too old or not configured " - "to support BPF programs loading"); - - return -ENOTSUP; - } - - rss_flow = rte_zmalloc(__func__, sizeof(struct rte_flow), 0); - if (!rss_flow) { - TAP_LOG(ERR, - "Cannot allocate memory for rte_flow"); - return -1; - } - msg = &rss_flow->msg; - tc_init_msg(msg, pmd->if_index, RTM_NEWTFILTER, NLM_F_REQUEST | - NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE); - msg->t.tcm_info = TC_H_MAKE(0, htons(ETH_P_ALL)); - tap_flow_set_handle(rss_flow); - uint16_t group = attr->group << GROUP_SHIFT; - uint16_t prio = group | (i + PRIORITY_OFFSET); - msg->t.tcm_info = TC_H_MAKE(prio << 16, msg->t.tcm_info); - msg->t.tcm_parent = TC_H_MAKE(MULTIQ_MAJOR_HANDLE, 0); - - tap_nlattr_add(&msg->nh, TCA_KIND, sizeof("bpf"), "bpf"); - if (tap_nlattr_nested_start(msg, TCA_OPTIONS) < 0) - return -1; - tap_nlattr_add32(&msg->nh, TCA_BPF_FD, pmd->bpf_fd[i]); - snprintf(annotation, sizeof(annotation), "[%s%d]", - SEC_NAME_CLS_Q, i); - tap_nlattr_add(&msg->nh, TCA_BPF_NAME, strlen(annotation) + 1, - annotation); - /* Actions */ - { - struct action_data adata = { - .id = "skbedit", - .skbedit = { - .skbedit = { - .action = TC_ACT_PIPE, - }, - .queue = i, - }, - }; - if (add_actions(rss_flow, 1, &adata, TCA_BPF_ACT) < 0) - return -1; - } - tap_nlattr_nested_finish(msg); /* nested TCA_OPTIONS */ + int err; - /* Netlink message is now ready to be sent */ - if (tap_nl_send(pmd->nlsk_fd, &msg->nh) < 0) - return -1; - err = tap_nl_recv_ack(pmd->nlsk_fd); - if (err < 0) { - TAP_LOG(ERR, - "Kernel refused TC filter rule creation (%d): %s", - errno, strerror(errno)); - return err; - } + /* Load the BPF program (defined in tap_bpf.h from skeleton) */ + pmd->rss = tap_rss__open_and_load(); + if (pmd->rss == NULL) { + TAP_LOG(ERR, "Failed to load BPF object: %s", strerror(errno)); + rte_flow_error_set(error, errno, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "BPF object could not be loaded"); + return -errno; } - pmd->rss_enabled = 1; - return err; -} - -/** - * Manage bpf RSS keys repository with operations: init, get, release - * - * @param[in] cmd - * Command on RSS keys: init, get, release - * - * @param[in, out] key_idx - * Pointer to RSS Key index (out for get command, in for release command) - * - * @return -1 if couldn't get, release or init the RSS keys, 0 otherwise. - */ -static int bpf_rss_key(enum bpf_rss_key_e cmd, __u32 *key_idx) -{ - __u32 i; - int err = 0; - static __u32 num_used_keys; - static __u32 rss_keys[MAX_RSS_KEYS] = {KEY_STAT_UNSPEC}; - static __u32 rss_keys_initialized; - __u32 key; - - switch (cmd) { - case KEY_CMD_GET: - if (!rss_keys_initialized) { - err = -1; - break; - } - - if (num_used_keys == RTE_DIM(rss_keys)) { - err = -1; - break; - } - - *key_idx = num_used_keys % RTE_DIM(rss_keys); - while (rss_keys[*key_idx] == KEY_STAT_USED) - *key_idx = (*key_idx + 1) % RTE_DIM(rss_keys); - - rss_keys[*key_idx] = KEY_STAT_USED; - - /* - * Add an offset to key_idx in order to handle a case of - * RSS and non RSS flows mixture. - * If a non RSS flow is destroyed it has an eBPF map - * index 0 (initialized on flow creation) and might - * unintentionally remove RSS entry 0 from eBPF map. - * To avoid this issue, add an offset to the real index - * during a KEY_CMD_GET operation and subtract this offset - * during a KEY_CMD_RELEASE operation in order to restore - * the real index. - */ - *key_idx += KEY_IDX_OFFSET; - num_used_keys++; - break; - - case KEY_CMD_RELEASE: - if (!rss_keys_initialized) - break; - - /* - * Subtract offset to restore real key index - * If a non RSS flow is falsely trying to release map - * entry 0 - the offset subtraction will calculate the real - * map index as an out-of-range value and the release operation - * will be silently ignored. - */ - key = *key_idx - KEY_IDX_OFFSET; - if (key >= RTE_DIM(rss_keys)) - break; - - if (rss_keys[key] == KEY_STAT_USED) { - rss_keys[key] = KEY_STAT_AVAILABLE; - num_used_keys--; - } - break; - - case KEY_CMD_INIT: - for (i = 0; i < RTE_DIM(rss_keys); i++) - rss_keys[i] = KEY_STAT_AVAILABLE; - - rss_keys_initialized = 1; - num_used_keys = 0; - break; - - case KEY_CMD_DEINIT: - for (i = 0; i < RTE_DIM(rss_keys); i++) - rss_keys[i] = KEY_STAT_UNSPEC; - - rss_keys_initialized = 0; - num_used_keys = 0; - break; - - default: - break; + /* Attach the maps defined in BPF program */ + err = tap_rss__attach(pmd->rss); + if (err < 0) { + TAP_LOG(ERR, "Failed to attach BPF object: %d", err); + rte_flow_error_set(error, -err, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "BPF object could not be attached"); + tap_flow_bpf_destroy(pmd); + return err; } - return err; + return 0; } - /* Default RSS hash key also used by mlx devices */ static const uint8_t rss_hash_default_key[] = { 0x2c, 0xc6, 0x81, 0xd1, @@ -2006,9 +1803,11 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd, const struct rte_flow_action_rss *rss, struct rte_flow_error *error) { + const struct bpf_program *rss_prog = pmd->rss->progs.rss_flow_action; struct rss_key rss_entry = { }; const uint8_t *key_in; uint32_t hash_type = 0; + uint32_t handle = flow->msg.t.tcm_handle; unsigned int i; int err; @@ -2057,34 +1856,24 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd, else if (rss->types & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | RTE_ETH_RSS_IPV6_EX)) hash_type |= RTE_BIT32(HASH_FIELD_IPV6_L3); - /* Get a new map key for a new RSS rule */ - err = bpf_rss_key(KEY_CMD_GET, &flow->key_idx); - if (err < 0) { - rte_flow_error_set( - error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, - "Failed to get BPF RSS key"); - - return -1; - } + rss_entry.hash_fields = hash_type; + rte_convert_rss_key((const uint32_t *)key_in, (uint32_t *)rss_entry.key, + TAP_RSS_HASH_KEY_SIZE); /* Update RSS map entry with queues */ rss_entry.nb_queues = rss->queue_num; for (i = 0; i < rss->queue_num; i++) rss_entry.queues[i] = rss->queue[i]; - rss_entry.hash_fields = hash_type; - rte_convert_rss_key((const uint32_t *)key_in, (uint32_t *)rss_entry.key, - TAP_RSS_HASH_KEY_SIZE); - - - /* Add this RSS entry to map */ - err = tap_flow_bpf_update_rss_elem(pmd->map_fd, - &flow->key_idx, &rss_entry); + /* Add this way for BPF to find entry in map */ + err = bpf_map__update_elem(pmd->rss->maps.rss_map, + &handle, sizeof(handle), + &rss_entry, sizeof(rss_entry), 0); if (err) { TAP_LOG(ERR, - "Failed to update BPF map entry #%u (%d): %s", - flow->key_idx, errno, strerror(errno)); + "Failed to update BPF map entry %#x (%d): %s", + handle, errno, strerror(errno)); rte_flow_error_set( error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "Kernel too old or not configured " @@ -2093,47 +1882,28 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd, return -ENOTSUP; } - - /* - * Load bpf rules to calculate hash for this key_idx - */ - - flow->bpf_fd[SEC_L3_L4] = - tap_flow_bpf_calc_l3_l4_hash(flow->key_idx, pmd->map_fd); - if (flow->bpf_fd[SEC_L3_L4] < 0) { - TAP_LOG(ERR, - "Failed to load BPF section %s (%d): %s", - sec_name[SEC_L3_L4], errno, strerror(errno)); - rte_flow_error_set( - error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, - "Kernel too old or not configured " - "to support BPF program loading"); - - return -ENOTSUP; - } - - /* Actions */ - { - struct action_data adata[] = { - { - .id = "bpf", - .bpf = { - .bpf_fd = flow->bpf_fd[SEC_L3_L4], - .annotation = sec_name[SEC_L3_L4], - .bpf = { - .action = TC_ACT_PIPE, - }, - }, + /* Add actions to mark packet then run the RSS BPF program */ + struct action_data adata[] = { + { + .id = "skbedit", + .skbedit = { + .skbedit.action = TC_ACT_PIPE, + .mark = handle, }, - }; - - if (add_actions(flow, RTE_DIM(adata), adata, - TCA_FLOWER_ACT) < 0) - return -1; - } + }, + { + .id = "bpf", + .bpf = { + .bpf.action = TC_ACT_PIPE, + .annotation = "tap_rss", + .bpf_fd = bpf_program__fd(rss_prog), + }, + }, + }; - return 0; + return add_actions(flow, RTE_DIM(adata), adata, TCA_FLOWER_ACT); } +#endif /** * Get rte_flow operations. diff --git a/drivers/net/tap/tap_flow.h b/drivers/net/tap/tap_flow.h index 240fbc3dfa..8b19347a93 100644 --- a/drivers/net/tap/tap_flow.h +++ b/drivers/net/tap/tap_flow.h @@ -9,7 +9,11 @@ #include #include #include -#include + +/** + * Mask of unsupported RSS types + */ +#define TAP_RSS_HF_MASK (~(RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP)) /** * In TC, priority 0 means we require the kernel to allocate one for us. @@ -41,11 +45,6 @@ enum implicit_rule_index { TAP_REMOTE_MAX_IDX, }; -enum bpf_fd_idx { - SEC_L3_L4, - SEC_MAX, -}; - int tap_dev_flow_ops_get(struct rte_eth_dev *dev, const struct rte_flow_ops **ops); int tap_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error); @@ -57,10 +56,6 @@ int tap_flow_implicit_destroy(struct pmd_internals *pmd, int tap_flow_implicit_flush(struct pmd_internals *pmd, struct rte_flow_error *error); -int tap_flow_bpf_cls_q(__u32 queue_idx); -int tap_flow_bpf_calc_l3_l4_hash(__u32 key_idx, int map_fd); -int tap_flow_bpf_rss_map_create(unsigned int key_size, unsigned int value_size, - unsigned int max_entries); -int tap_flow_bpf_update_rss_elem(int fd, void *key, void *value); +void tap_flow_bpf_destroy(struct pmd_internals *pmd); #endif /* _TAP_FLOW_H_ */ diff --git a/drivers/net/tap/tap_rss.h b/drivers/net/tap/tap_rss.h index 6009be7031..65bd8991b1 100644 --- a/drivers/net/tap/tap_rss.h +++ b/drivers/net/tap/tap_rss.h @@ -5,16 +5,14 @@ #ifndef _TAP_RSS_H_ #define _TAP_RSS_H_ -#ifndef TAP_MAX_QUEUES -#define TAP_MAX_QUEUES 16 +/* Size of the map from BPF classid to queue table */ +#ifndef TAP_RSS_MAX +#define TAP_RSS_MAX 32 #endif -/* Fixed RSS hash key size in bytes. */ +/* Standard Toeplitz hash key size */ #define TAP_RSS_HASH_KEY_SIZE 40 -/* Supported RSS */ -#define TAP_RSS_HF_MASK (~(RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP)) - /* hashed fields for RSS */ enum hash_field { HASH_FIELD_IPV4_L3, /* IPv4 src/dst addr */ diff --git a/drivers/net/tap/tap_tcmsgs.h b/drivers/net/tap/tap_tcmsgs.h index a64cb29d6f..00a0f22e31 100644 --- a/drivers/net/tap/tap_tcmsgs.h +++ b/drivers/net/tap/tap_tcmsgs.h @@ -6,7 +6,6 @@ #ifndef _TAP_TCMSGS_H_ #define _TAP_TCMSGS_H_ -#include #include #include #include @@ -14,9 +13,8 @@ #include #include #include -#ifdef HAVE_TC_ACT_BPF #include -#endif + #include #include From patchwork Mon Apr 8 21:18:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 139197 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id A8D7D43DD2; Mon, 8 Apr 2024 23:25:39 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0B94840A80; Mon, 8 Apr 2024 23:24:54 +0200 (CEST) Received: from mail-io1-f54.google.com (mail-io1-f54.google.com [209.85.166.54]) by mails.dpdk.org (Postfix) with ESMTP id 3930340695 for ; Mon, 8 Apr 2024 23:24:49 +0200 (CEST) Received: by mail-io1-f54.google.com with SMTP id ca18e2360f4ac-7d0486cf91aso264601639f.1 for ; Mon, 08 Apr 2024 14:24:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712611488; x=1713216288; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=k65SDCHwmSyyBJZ8DiohRCGj/brh5bz3P4txRIRxCW8=; b=j62SsDjkKq3SctsRPxAJ6KqnoYVWhh7NXmKdOwVU+PA9G2KIVpCMYJ5bIggHHEZu8W CR9hkMKYwbLPiQCmWx2LBMjul2QQ4TIglheJa9Zc5obQV6CarE2vfnoiLSKor1VmsUFv rX7skgaOMJWZ6f7fBizDwzCG0JZLcFfTl3QRy1ZUCPE8En3q7dr6MPyKBBqQOTJhcGTO qbXWNjEka3WxbVxsbGTXN1MXPrsSGkmbL4RnQUrFl27Mh/EGKqyI+jeGxQ6URQ4OaA0A 4S+XLOYFjA16N+NuysmO+botgdqLbGbvIh/T4dI29kQKCjMstHxDAPf6Brwlr2pJIcpy sGLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712611488; x=1713216288; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=k65SDCHwmSyyBJZ8DiohRCGj/brh5bz3P4txRIRxCW8=; b=Dox7S0fvSs1xQIhpdcmGtTjCdnPnw4c0mSZlfz9NdW2pg44D9Uqe/8TnQxwrtJYdw4 YFM2j+/KrFjomu2Cks7ZKsRjelTIGfYHLxMQsAcqmGGYBhZIJfdgBZACLdLu+eGfOGHY RtRefYVtDnh23iDdnBF/4j2kLwpt6hXn/J8rreYqCKJm2rq3icEnas4SRzYgPJ1NChWe 7PqlXNlBIxxUgemopou62DCtN5LNTY/G1U9QLzq1wrzyfO9G1F8+0PGHRNIqdKofYhCs nkSawzHOEYgQdg0iI2E4V/K6sEwd3ayYP/o8S1Q6FsAxQWad7g4v1rRdTlk3W7AqCfxm VAMA== X-Gm-Message-State: AOJu0YxyhzG+A0eb05e5mkkeWulAHD2H6+C+EkaZmpy3YZhWVIMJZeXa jG1aWre5AWvg3J7zQIZqOul4Q1sLV6DWTvr/VzxeyzIiPlHMWJp3M8RC694eQ/d+G0Nkv34z4IA U0Is= X-Google-Smtp-Source: AGHT+IFRObdyqlZitpQMioZXLtC9Od6ENyxxqLckAYZKrpIo/X8zF11pR1k/64en0T0cAmIjKD7XLw== X-Received: by 2002:a05:6e02:1a02:b0:36a:22e8:d379 with SMTP id s2-20020a056e021a0200b0036a22e8d379mr6543458ild.10.1712611487948; Mon, 08 Apr 2024 14:24:47 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id f16-20020a633810000000b005e43cce33f8sm6924725pga.88.2024.04.08.14.24.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Apr 2024 14:24:47 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v7 7/8] net/tap: remove no longer used files Date: Mon, 8 Apr 2024 14:18:38 -0700 Message-ID: <20240408212438.414099-8-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240408212438.414099-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240408212438.414099-1-stephen@networkplumber.org> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The BPF api was replaced by use of libbpf. And the BPF instruction header was replaced by the skeleton. Signed-off-by: Stephen Hemminger --- drivers/net/tap/tap_bpf_api.c | 196 ---- drivers/net/tap/tap_bpf_insns.h | 1741 ------------------------------- 2 files changed, 1937 deletions(-) delete mode 100644 drivers/net/tap/tap_bpf_api.c delete mode 100644 drivers/net/tap/tap_bpf_insns.h diff --git a/drivers/net/tap/tap_bpf_api.c b/drivers/net/tap/tap_bpf_api.c deleted file mode 100644 index 9e05e2ddf1..0000000000 --- a/drivers/net/tap/tap_bpf_api.c +++ /dev/null @@ -1,196 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2017 Mellanox Technologies, Ltd - */ - -#include -#include -#include - -#include -#include - -#include - - -static int bpf_load(enum bpf_prog_type type, const struct bpf_insn *insns, - size_t insns_cnt, const char *license); - -/** - * Load BPF program (section cls_q) into the kernel and return a bpf fd - * - * @param queue_idx - * Queue index matching packet cb - * - * @return - * -1 if the BPF program couldn't be loaded. An fd (int) otherwise. - */ -int tap_flow_bpf_cls_q(__u32 queue_idx) -{ - cls_q_insns[1].imm = queue_idx; - - return bpf_load(BPF_PROG_TYPE_SCHED_CLS, - (struct bpf_insn *)cls_q_insns, - RTE_DIM(cls_q_insns), - "Dual BSD/GPL"); -} - -/** - * Load BPF program (section l3_l4) into the kernel and return a bpf fd. - * - * @param[in] key_idx - * RSS MAP key index - * - * @param[in] map_fd - * BPF RSS map file descriptor - * - * @return - * -1 if the BPF program couldn't be loaded. An fd (int) otherwise. - */ -int tap_flow_bpf_calc_l3_l4_hash(__u32 key_idx, int map_fd) -{ - l3_l4_hash_insns[4].imm = key_idx; - l3_l4_hash_insns[9].imm = map_fd; - - return bpf_load(BPF_PROG_TYPE_SCHED_ACT, - (struct bpf_insn *)l3_l4_hash_insns, - RTE_DIM(l3_l4_hash_insns), - "Dual BSD/GPL"); -} - -/** - * Helper function to convert a pointer to unsigned 64 bits - * - * @param[in] ptr - * pointer to address - * - * @return - * 64 bit unsigned long type of pointer address - */ -static inline __u64 ptr_to_u64(const void *ptr) -{ - return (__u64)(unsigned long)ptr; -} - -/** - * Call BPF system call - * - * @param[in] cmd - * BPF command for program loading, map creation, map entry update, etc - * - * @param[in] attr - * System call attributes relevant to system call command - * - * @param[in] size - * size of attr parameter - * - * @return - * -1 if BPF system call failed, 0 otherwise - */ -static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, - unsigned int size) -{ -#ifdef __NR_bpf - return syscall(__NR_bpf, cmd, attr, size); -#else - TAP_LOG(ERR, "No bpf syscall, kernel headers too old?\n"); - errno = ENOSYS; - return -1; -#endif -} - -/** - * Load BPF instructions to kernel - * - * @param[in] type - * BPF program type: classifier or action - * - * @param[in] insns - * Array of BPF instructions (equivalent to BPF instructions) - * - * @param[in] insns_cnt - * Number of BPF instructions (size of array) - * - * @param[in] license - * License string that must be acknowledged by the kernel - * - * @return - * -1 if the BPF program couldn't be loaded, fd (file descriptor) otherwise - */ -static int bpf_load(enum bpf_prog_type type, - const struct bpf_insn *insns, - size_t insns_cnt, - const char *license) -{ - union bpf_attr attr = {}; - - bzero(&attr, sizeof(attr)); - attr.prog_type = type; - attr.insn_cnt = (__u32)insns_cnt; - attr.insns = ptr_to_u64(insns); - attr.license = ptr_to_u64(license); - attr.log_buf = ptr_to_u64(NULL); - attr.log_level = 0; - attr.kern_version = 0; - - return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); -} - -/** - * Create BPF map for RSS rules - * - * @param[in] key_size - * map RSS key size - * - * @param[in] value_size - * Map RSS value size - * - * @param[in] max_entries - * Map max number of RSS entries (limit on max RSS rules) - * - * @return - * -1 if BPF map couldn't be created, map fd otherwise - */ -int tap_flow_bpf_rss_map_create(unsigned int key_size, - unsigned int value_size, - unsigned int max_entries) -{ - union bpf_attr attr = {}; - - bzero(&attr, sizeof(attr)); - attr.map_type = BPF_MAP_TYPE_HASH; - attr.key_size = key_size; - attr.value_size = value_size; - attr.max_entries = max_entries; - - return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); -} - -/** - * Update RSS entry in BPF map - * - * @param[in] fd - * RSS map fd - * - * @param[in] key - * Pointer to RSS key whose entry is updated - * - * @param[in] value - * Pointer to RSS new updated value - * - * @return - * -1 if RSS entry failed to be updated, 0 otherwise - */ -int tap_flow_bpf_update_rss_elem(int fd, void *key, void *value) -{ - union bpf_attr attr = {}; - - bzero(&attr, sizeof(attr)); - - attr.map_type = BPF_MAP_TYPE_HASH; - attr.map_fd = fd; - attr.key = ptr_to_u64(key); - attr.value = ptr_to_u64(value); - attr.flags = BPF_ANY; - - return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); -} diff --git a/drivers/net/tap/tap_bpf_insns.h b/drivers/net/tap/tap_bpf_insns.h deleted file mode 100644 index cdf2febf05..0000000000 --- a/drivers/net/tap/tap_bpf_insns.h +++ /dev/null @@ -1,1741 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Auto-generated from tap_bpf_program.c - * This not the original source file. Do NOT edit it. - */ - -static struct bpf_insn cls_q_insns[] = { - {0x61, 2, 1, 52, 0x00000000}, - {0x18, 3, 0, 0, 0xdeadbeef}, - {0x00, 0, 0, 0, 0x00000000}, - {0x63, 10, 3, -4, 0x00000000}, - {0xb7, 0, 0, 0, 0x00000000}, - {0x61, 3, 10, -4, 0x00000000}, - {0x07, 3, 0, 0, 0x7cafe800}, - {0x67, 3, 0, 0, 0x00000020}, - {0x77, 3, 0, 0, 0x00000020}, - {0x5d, 2, 3, 4, 0x00000000}, - {0xb7, 2, 0, 0, 0x00000000}, - {0x63, 1, 2, 52, 0x00000000}, - {0x18, 0, 0, 0, 0xffffffff}, - {0x00, 0, 0, 0, 0x00000000}, - {0x95, 0, 0, 0, 0x00000000}, -}; - -static struct bpf_insn l3_l4_hash_insns[] = { - {0xbf, 7, 1, 0, 0x00000000}, - {0x61, 6, 7, 16, 0x00000000}, - {0x61, 8, 7, 76, 0x00000000}, - {0x61, 9, 7, 80, 0x00000000}, - {0x18, 1, 0, 0, 0xdeadbeef}, - {0x00, 0, 0, 0, 0x00000000}, - {0x63, 10, 1, -4, 0x00000000}, - {0xbf, 2, 10, 0, 0x00000000}, - {0x07, 2, 0, 0, 0xfffffffc}, - {0x18, 1, 0, 0, 0x00000000}, - {0x00, 0, 0, 0, 0x00000000}, - {0x85, 0, 0, 0, 0x00000001}, - {0x55, 0, 0, 21, 0x00000000}, - {0xb7, 1, 0, 0, 0x00000a64}, - {0x6b, 10, 1, -16, 0x00000000}, - {0x18, 1, 0, 0, 0x69666e6f}, - {0x00, 0, 0, 0, 0x65727567}, - {0x7b, 10, 1, -24, 0x00000000}, - {0x18, 1, 0, 0, 0x6e207369}, - {0x00, 0, 0, 0, 0x6320746f}, - {0x7b, 10, 1, -32, 0x00000000}, - {0x18, 1, 0, 0, 0x20737372}, - {0x00, 0, 0, 0, 0x2079656b}, - {0x7b, 10, 1, -40, 0x00000000}, - {0x18, 1, 0, 0, 0x68736168}, - {0x00, 0, 0, 0, 0x203a2928}, - {0x7b, 10, 1, -48, 0x00000000}, - {0xb7, 7, 0, 0, 0x00000000}, - {0x73, 10, 7, -14, 0x00000000}, - {0xbf, 1, 10, 0, 0x00000000}, - {0x07, 1, 0, 0, 0xffffffd0}, - {0xb7, 2, 0, 0, 0x00000023}, - {0x85, 0, 0, 0, 0x00000006}, - {0x05, 0, 0, 1680, 0x00000000}, - {0xb7, 1, 0, 0, 0x0000000e}, - {0x61, 2, 7, 20, 0x00000000}, - {0x15, 2, 0, 10, 0x00000000}, - {0x61, 2, 7, 28, 0x00000000}, - {0x55, 2, 0, 8, 0x0000a888}, - {0xbf, 2, 7, 0, 0x00000000}, - {0xb7, 7, 0, 0, 0x00000000}, - {0xbf, 1, 8, 0, 0x00000000}, - {0x07, 1, 0, 0, 0x00000012}, - {0x2d, 1, 9, 1670, 0x00000000}, - {0xb7, 1, 0, 0, 0x00000012}, - {0x69, 6, 8, 16, 0x00000000}, - {0xbf, 7, 2, 0, 0x00000000}, - {0x57, 6, 0, 0, 0x0000ffff}, - {0x7b, 10, 7, -56, 0x00000000}, - {0x15, 6, 0, 443, 0x0000dd86}, - {0xb7, 7, 0, 0, 0x00000003}, - {0x55, 6, 0, 1662, 0x00000008}, - {0x0f, 8, 1, 0, 0x00000000}, - {0xb7, 7, 0, 0, 0x00000000}, - {0xbf, 1, 8, 0, 0x00000000}, - {0x07, 1, 0, 0, 0x00000018}, - {0x2d, 1, 9, 1657, 0x00000000}, - {0xb7, 1, 0, 0, 0x00000000}, - {0x71, 3, 8, 12, 0x00000000}, - {0x71, 2, 8, 9, 0x00000000}, - {0x15, 2, 0, 1, 0x00000011}, - {0x55, 2, 0, 21, 0x00000006}, - {0x71, 2, 8, 7, 0x00000000}, - {0x71, 4, 8, 6, 0x00000000}, - {0xbf, 5, 4, 0, 0x00000000}, - {0x67, 5, 0, 0, 0x00000008}, - {0x57, 5, 0, 0, 0x00001f00}, - {0x4f, 5, 2, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000020}, - {0x4f, 4, 5, 0, 0x00000000}, - {0x55, 4, 0, 12, 0x00000000}, - {0xbf, 2, 8, 0, 0x00000000}, - {0x07, 2, 0, 0, 0x00000014}, - {0x71, 4, 2, 0, 0x00000000}, - {0x67, 4, 0, 0, 0x00000018}, - {0x71, 1, 2, 1, 0x00000000}, - {0x67, 1, 0, 0, 0x00000010}, - {0x4f, 1, 4, 0, 0x00000000}, - {0x71, 4, 2, 3, 0x00000000}, - {0x4f, 1, 4, 0, 0x00000000}, - {0x71, 2, 2, 2, 0x00000000}, - {0x67, 2, 0, 0, 0x00000008}, - {0x4f, 1, 2, 0, 0x00000000}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x67, 4, 0, 0, 0x00000038}, - {0xc7, 4, 0, 0, 0x00000038}, - {0xb7, 2, 0, 0, 0x00000000}, - {0x65, 4, 0, 1, 0xffffffff}, - {0xb7, 7, 0, 0, 0x2cc681d1}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000040}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x598d03a2}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000020}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xb31a0745}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000010}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x66340e8a}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000008}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xcc681d15}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000004}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x98d03a2b}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000002}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x31a07456}, - {0x71, 4, 8, 13, 0x00000000}, - {0x57, 3, 0, 0, 0x00000001}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x6340e8ad}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x67, 3, 0, 0, 0x00000038}, - {0xc7, 3, 0, 0, 0x00000038}, - {0xbf, 5, 7, 0, 0x00000000}, - {0xa7, 5, 0, 0, 0xc681d15b}, - {0x6d, 2, 3, 1, 0x00000000}, - {0xbf, 5, 7, 0, 0x00000000}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000040}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x8d03a2b7}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000020}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x1a07456f}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000010}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x340e8ade}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000008}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x681d15bd}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000004}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xd03a2b7b}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000002}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xa07456f6}, - {0x71, 3, 8, 14, 0x00000000}, - {0x57, 4, 0, 0, 0x00000001}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x40e8aded}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x67, 4, 0, 0, 0x00000038}, - {0xc7, 4, 0, 0, 0x00000038}, - {0xbf, 7, 5, 0, 0x00000000}, - {0xa7, 7, 0, 0, 0x81d15bdb}, - {0x6d, 2, 4, 1, 0x00000000}, - {0xbf, 7, 5, 0, 0x00000000}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000040}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x03a2b7b7}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000020}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x07456f6f}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000010}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x0e8adedf}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000008}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x1d15bdbf}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000004}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x3a2b7b7e}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000002}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x7456f6fd}, - {0x71, 4, 8, 15, 0x00000000}, - {0x57, 3, 0, 0, 0x00000001}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xe8adedfa}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x67, 3, 0, 0, 0x00000038}, - {0xc7, 3, 0, 0, 0x00000038}, - {0xbf, 5, 7, 0, 0x00000000}, - {0xa7, 5, 0, 0, 0xd15bdbf4}, - {0x6d, 2, 3, 1, 0x00000000}, - {0xbf, 5, 7, 0, 0x00000000}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000040}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xa2b7b7e9}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000020}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x456f6fd3}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000010}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x8adedfa7}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000008}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x15bdbf4f}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000004}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x2b7b7e9e}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000002}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x56f6fd3d}, - {0x71, 3, 8, 16, 0x00000000}, - {0x57, 4, 0, 0, 0x00000001}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xadedfa7b}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x67, 4, 0, 0, 0x00000038}, - {0xc7, 4, 0, 0, 0x00000038}, - {0xbf, 7, 5, 0, 0x00000000}, - {0xa7, 7, 0, 0, 0x5bdbf4f7}, - {0x6d, 2, 4, 1, 0x00000000}, - {0xbf, 7, 5, 0, 0x00000000}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000040}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xb7b7e9ef}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000020}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x6f6fd3df}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000010}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xdedfa7bf}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000008}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xbdbf4f7f}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000004}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x7b7e9eff}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000002}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xf6fd3dff}, - {0x71, 4, 8, 17, 0x00000000}, - {0x57, 3, 0, 0, 0x00000001}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xedfa7bfe}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x67, 3, 0, 0, 0x00000038}, - {0xc7, 3, 0, 0, 0x00000038}, - {0xbf, 5, 7, 0, 0x00000000}, - {0xa7, 5, 0, 0, 0xdbf4f7fc}, - {0x6d, 2, 3, 1, 0x00000000}, - {0xbf, 5, 7, 0, 0x00000000}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000040}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xb7e9eff9}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000020}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x6fd3dff2}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000010}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xdfa7bfe5}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000008}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xbf4f7fca}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000004}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x7e9eff94}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000002}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xfd3dff28}, - {0x71, 3, 8, 18, 0x00000000}, - {0x57, 4, 0, 0, 0x00000001}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xfa7bfe51}, - {0xbf, 6, 3, 0, 0x00000000}, - {0x67, 6, 0, 0, 0x00000038}, - {0xc7, 6, 0, 0, 0x00000038}, - {0xbf, 4, 5, 0, 0x00000000}, - {0xa7, 4, 0, 0, 0xf4f7fca2}, - {0x6d, 2, 6, 1, 0x00000000}, - {0xbf, 4, 5, 0, 0x00000000}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000040}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xe9eff945}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000020}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xd3dff28a}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000010}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xa7bfe514}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000008}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x4f7fca28}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000004}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x9eff9450}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000002}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x3dff28a0}, - {0x71, 5, 8, 19, 0x00000000}, - {0x57, 3, 0, 0, 0x00000001}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x7bfe5141}, - {0xbf, 3, 5, 0, 0x00000000}, - {0x67, 3, 0, 0, 0x00000038}, - {0xc7, 3, 0, 0, 0x00000038}, - {0xbf, 7, 4, 0, 0x00000000}, - {0xa7, 7, 0, 0, 0xf7fca283}, - {0x6d, 2, 3, 1, 0x00000000}, - {0xbf, 7, 4, 0, 0x00000000}, - {0xbf, 3, 5, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000040}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xeff94506}, - {0xbf, 3, 5, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000020}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xdff28a0c}, - {0xbf, 3, 5, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000010}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xbfe51418}, - {0xbf, 3, 5, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000008}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x7fca2831}, - {0xbf, 3, 5, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000004}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xff945063}, - {0xbf, 3, 5, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000002}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xff28a0c6}, - {0x57, 5, 0, 0, 0x00000001}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xfe51418c}, - {0xbf, 4, 1, 0, 0x00000000}, - {0x67, 4, 0, 0, 0x00000020}, - {0xc7, 4, 0, 0, 0x00000020}, - {0xbf, 3, 7, 0, 0x00000000}, - {0xa7, 3, 0, 0, 0xfca28319}, - {0x6d, 2, 4, 1, 0x00000000}, - {0xbf, 3, 7, 0, 0x00000000}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x40000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xf9450633}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x20000000}, - {0x79, 6, 10, -56, 0x00000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xf28a0c67}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x10000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xe51418ce}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x08000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xca28319d}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x04000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x9450633b}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x02000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x28a0c676}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x01000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x51418ced}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00800000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xa28319db}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00400000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x450633b6}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00200000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x8a0c676c}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00100000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x1418ced8}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00080000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x28319db1}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00040000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x50633b63}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00020000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xa0c676c6}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00010000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x418ced8d}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00008000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x8319db1a}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00004000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x0633b634}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00002000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x0c676c68}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00001000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x18ced8d1}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000800}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x319db1a3}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000400}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x633b6347}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000200}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xc676c68f}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000100}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x8ced8d1f}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000080}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x19db1a3e}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000040}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x33b6347d}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000020}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x676c68fa}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000010}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xced8d1f4}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000008}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x9db1a3e9}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000004}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x3b6347d2}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000002}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x76c68fa5}, - {0x57, 1, 0, 0, 0x00000001}, - {0x15, 1, 0, 1194, 0x00000000}, - {0xa7, 3, 0, 0, 0xed8d1f4a}, - {0x05, 0, 0, 1192, 0x00000000}, - {0x0f, 8, 1, 0, 0x00000000}, - {0xb7, 7, 0, 0, 0x00000000}, - {0xbf, 1, 8, 0, 0x00000000}, - {0x07, 1, 0, 0, 0x0000002c}, - {0x2d, 1, 9, 1216, 0x00000000}, - {0x61, 2, 8, 8, 0x00000000}, - {0xdc, 2, 0, 0, 0x00000040}, - {0xc7, 2, 0, 0, 0x00000020}, - {0x71, 3, 8, 6, 0x00000000}, - {0x15, 3, 0, 2, 0x00000011}, - {0xb7, 1, 0, 0, 0x00000000}, - {0x55, 3, 0, 12, 0x00000006}, - {0xbf, 3, 8, 0, 0x00000000}, - {0x07, 3, 0, 0, 0x00000028}, - {0x71, 4, 3, 0, 0x00000000}, - {0x67, 4, 0, 0, 0x00000018}, - {0x71, 1, 3, 1, 0x00000000}, - {0x67, 1, 0, 0, 0x00000010}, - {0x4f, 1, 4, 0, 0x00000000}, - {0x71, 4, 3, 3, 0x00000000}, - {0x4f, 1, 4, 0, 0x00000000}, - {0x71, 3, 3, 2, 0x00000000}, - {0x67, 3, 0, 0, 0x00000008}, - {0x4f, 1, 3, 0, 0x00000000}, - {0xbf, 4, 2, 0, 0x00000000}, - {0x77, 4, 0, 0, 0x0000001f}, - {0x57, 4, 0, 0, 0x2cc681d1}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x40000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x598d03a2}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x20000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xb31a0745}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x10000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x66340e8a}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x08000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xcc681d15}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x04000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x98d03a2b}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x02000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x31a07456}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x01000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x6340e8ad}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00800000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xc681d15b}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00400000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x8d03a2b7}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00200000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x1a07456f}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00100000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x340e8ade}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00080000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x681d15bd}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00040000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xd03a2b7b}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00020000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xa07456f6}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00010000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x40e8aded}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00008000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x81d15bdb}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00004000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x03a2b7b7}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00002000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x07456f6f}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00001000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x0e8adedf}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000800}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x1d15bdbf}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000400}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x3a2b7b7e}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000200}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x7456f6fd}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000100}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xe8adedfa}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000080}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xd15bdbf4}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000040}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xa2b7b7e9}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000020}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x456f6fd3}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000010}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x8adedfa7}, - {0xbf, 3, 2, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000008}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x15bdbf4f}, - {0x61, 3, 8, 12, 0x00000000}, - {0xbf, 5, 2, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000004}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x2b7b7e9e}, - {0xdc, 3, 0, 0, 0x00000040}, - {0xbf, 5, 2, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000002}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x56f6fd3d}, - {0xc7, 3, 0, 0, 0x00000020}, - {0x57, 2, 0, 0, 0x00000001}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xadedfa7b}, - {0xb7, 2, 0, 0, 0x00000000}, - {0xbf, 5, 4, 0, 0x00000000}, - {0xa7, 5, 0, 0, 0x5bdbf4f7}, - {0x6d, 2, 3, 1, 0x00000000}, - {0xbf, 5, 4, 0, 0x00000000}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x40000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xb7b7e9ef}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x20000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x6f6fd3df}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x10000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xdedfa7bf}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x08000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xbdbf4f7f}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x04000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x7b7e9eff}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x02000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xf6fd3dff}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x01000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xedfa7bfe}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00800000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xdbf4f7fc}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00400000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xb7e9eff9}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00200000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x6fd3dff2}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00100000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xdfa7bfe5}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00080000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xbf4f7fca}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00040000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x7e9eff94}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00020000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xfd3dff28}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00010000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xfa7bfe51}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00008000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xf4f7fca2}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00004000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xe9eff945}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00002000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xd3dff28a}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00001000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xa7bfe514}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000800}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x4f7fca28}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000400}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x9eff9450}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000200}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x3dff28a0}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000100}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x7bfe5141}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000080}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xf7fca283}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000040}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xeff94506}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000020}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xdff28a0c}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000010}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xbfe51418}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000008}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x7fca2831}, - {0x61, 4, 8, 16, 0x00000000}, - {0xbf, 6, 3, 0, 0x00000000}, - {0x57, 6, 0, 0, 0x00000004}, - {0x15, 6, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xff945063}, - {0xdc, 4, 0, 0, 0x00000040}, - {0xbf, 6, 3, 0, 0x00000000}, - {0x57, 6, 0, 0, 0x00000002}, - {0x15, 6, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xff28a0c6}, - {0xc7, 4, 0, 0, 0x00000020}, - {0x57, 3, 0, 0, 0x00000001}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xfe51418c}, - {0xbf, 7, 5, 0, 0x00000000}, - {0xa7, 7, 0, 0, 0xfca28319}, - {0x6d, 2, 4, 1, 0x00000000}, - {0xbf, 7, 5, 0, 0x00000000}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x40000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xf9450633}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x20000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xf28a0c67}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x10000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xe51418ce}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x08000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xca28319d}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x04000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x9450633b}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x02000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x28a0c676}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x01000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x51418ced}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00800000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xa28319db}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00400000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x450633b6}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00200000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x8a0c676c}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00100000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x1418ced8}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00080000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x28319db1}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00040000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x50633b63}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00020000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xa0c676c6}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00010000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x418ced8d}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00008000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x8319db1a}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00004000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x0633b634}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00002000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x0c676c68}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00001000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x18ced8d1}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000800}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x319db1a3}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000400}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x633b6347}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000200}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xc676c68f}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000100}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x8ced8d1f}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000080}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x19db1a3e}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000040}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x33b6347d}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000020}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x676c68fa}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000010}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xced8d1f4}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000008}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x9db1a3e9}, - {0x61, 3, 8, 20, 0x00000000}, - {0xbf, 5, 4, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000004}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x3b6347d2}, - {0xdc, 3, 0, 0, 0x00000040}, - {0xbf, 5, 4, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000002}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x76c68fa5}, - {0xc7, 3, 0, 0, 0x00000020}, - {0x57, 4, 0, 0, 0x00000001}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xed8d1f4a}, - {0xbf, 5, 7, 0, 0x00000000}, - {0xa7, 5, 0, 0, 0xdb1a3e94}, - {0x6d, 2, 3, 1, 0x00000000}, - {0xbf, 5, 7, 0, 0x00000000}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x40000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xb6347d28}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x20000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x6c68fa51}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x10000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xd8d1f4a3}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x08000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xb1a3e946}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x04000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x6347d28d}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x02000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xc68fa51a}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x01000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x8d1f4a35}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00800000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x1a3e946b}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00400000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x347d28d7}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00200000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x68fa51ae}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00100000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xd1f4a35c}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00080000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xa3e946b9}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00040000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x47d28d73}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00020000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x8fa51ae7}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00010000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x1f4a35cf}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00008000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x3e946b9e}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00004000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x7d28d73c}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00002000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xfa51ae78}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00001000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xf4a35cf1}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000800}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xe946b9e3}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000400}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xd28d73c7}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000200}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xa51ae78e}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000100}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x4a35cf1c}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000080}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x946b9e38}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000040}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x28d73c71}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000020}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x51ae78e3}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000010}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xa35cf1c6}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000008}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x46b9e38d}, - {0x61, 4, 8, 24, 0x00000000}, - {0xbf, 6, 3, 0, 0x00000000}, - {0x57, 6, 0, 0, 0x00000004}, - {0x15, 6, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x8d73c71b}, - {0xdc, 4, 0, 0, 0x00000040}, - {0xbf, 6, 3, 0, 0x00000000}, - {0x57, 6, 0, 0, 0x00000002}, - {0x15, 6, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x1ae78e36}, - {0xc7, 4, 0, 0, 0x00000020}, - {0x57, 3, 0, 0, 0x00000001}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x35cf1c6c}, - {0xbf, 7, 5, 0, 0x00000000}, - {0xa7, 7, 0, 0, 0x6b9e38d9}, - {0x6d, 2, 4, 1, 0x00000000}, - {0xbf, 7, 5, 0, 0x00000000}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x40000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xd73c71b2}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x20000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xae78e364}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x10000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x5cf1c6c9}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x08000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xb9e38d92}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x04000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x73c71b25}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x02000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xe78e364b}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x01000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xcf1c6c96}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00800000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x9e38d92c}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00400000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x3c71b259}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00200000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x78e364b2}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00100000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xf1c6c964}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00080000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xe38d92c9}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00040000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xc71b2593}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00020000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x8e364b27}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00010000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x1c6c964e}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00008000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x38d92c9c}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00004000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x71b25938}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00002000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xe364b270}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00001000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xc6c964e0}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000800}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x8d92c9c0}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000400}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x1b259380}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000200}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x364b2700}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000100}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x6c964e01}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000080}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xd92c9c03}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000040}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xb2593807}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000020}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x64b2700f}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000010}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xc964e01e}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000008}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x92c9c03d}, - {0x61, 3, 8, 28, 0x00000000}, - {0xbf, 5, 4, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000004}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x2593807a}, - {0xdc, 3, 0, 0, 0x00000040}, - {0xbf, 5, 4, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000002}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x4b2700f4}, - {0xc7, 3, 0, 0, 0x00000020}, - {0x57, 4, 0, 0, 0x00000001}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x964e01e8}, - {0xbf, 5, 7, 0, 0x00000000}, - {0xa7, 5, 0, 0, 0x2c9c03d1}, - {0x6d, 2, 3, 1, 0x00000000}, - {0xbf, 5, 7, 0, 0x00000000}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x40000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x593807a3}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x20000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xb2700f46}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x10000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x64e01e8d}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x08000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xc9c03d1a}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x04000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x93807a35}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x02000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x2700f46b}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x01000000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x4e01e8d6}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00800000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x9c03d1ad}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00400000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x3807a35b}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00200000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x700f46b6}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00100000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xe01e8d6c}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00080000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xc03d1ad9}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00040000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x807a35b3}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00020000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x00f46b66}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00010000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x01e8d6cc}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00008000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x03d1ad99}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00004000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x07a35b32}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00002000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x0f46b665}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00001000}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x1e8d6cca}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000800}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x3d1ad994}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000400}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x7a35b328}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000200}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xf46b6651}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000100}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xe8d6cca2}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000080}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xd1ad9944}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000040}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xa35b3289}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000020}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x46b66512}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000010}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x8d6cca25}, - {0xbf, 4, 3, 0, 0x00000000}, - {0x57, 4, 0, 0, 0x00000008}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x1ad9944a}, - {0x61, 4, 8, 32, 0x00000000}, - {0xbf, 6, 3, 0, 0x00000000}, - {0x57, 6, 0, 0, 0x00000004}, - {0x15, 6, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x35b32894}, - {0xdc, 4, 0, 0, 0x00000040}, - {0xbf, 6, 3, 0, 0x00000000}, - {0x57, 6, 0, 0, 0x00000002}, - {0x15, 6, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0x6b665129}, - {0xc7, 4, 0, 0, 0x00000020}, - {0x57, 3, 0, 0, 0x00000001}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 5, 0, 0, 0xd6cca253}, - {0xbf, 7, 5, 0, 0x00000000}, - {0xa7, 7, 0, 0, 0xad9944a7}, - {0x6d, 2, 4, 1, 0x00000000}, - {0xbf, 7, 5, 0, 0x00000000}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x40000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x5b32894f}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x20000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xb665129f}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x10000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x6cca253e}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x08000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xd9944a7d}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x04000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xb32894fb}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x02000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x665129f6}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x01000000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xcca253ec}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00800000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x9944a7d9}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00400000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x32894fb2}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00200000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x65129f65}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00100000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xca253eca}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00080000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x944a7d95}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00040000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x2894fb2a}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00020000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x5129f655}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00010000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xa253ecab}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00008000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x44a7d956}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00004000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x894fb2ac}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00002000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x129f6558}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00001000}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x253ecab1}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000800}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x4a7d9563}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000400}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x94fb2ac7}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000200}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x29f6558f}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000100}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x53ecab1e}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000080}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xa7d9563d}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000040}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x4fb2ac7a}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000020}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x9f6558f5}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000010}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x3ecab1ea}, - {0xbf, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x00000008}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0x7d9563d5}, - {0x61, 3, 8, 36, 0x00000000}, - {0xbf, 5, 4, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000004}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xfb2ac7ab}, - {0xdc, 3, 0, 0, 0x00000040}, - {0xbf, 5, 4, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000002}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xf6558f56}, - {0xc7, 3, 0, 0, 0x00000020}, - {0x57, 4, 0, 0, 0x00000001}, - {0x15, 4, 0, 1, 0x00000000}, - {0xa7, 7, 0, 0, 0xecab1eac}, - {0xbf, 4, 7, 0, 0x00000000}, - {0xa7, 4, 0, 0, 0xd9563d59}, - {0x6d, 2, 3, 1, 0x00000000}, - {0xbf, 4, 7, 0, 0x00000000}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x40000000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xb2ac7ab2}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x20000000}, - {0x79, 6, 10, -56, 0x00000000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x6558f564}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x10000000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xcab1eac8}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x08000000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x9563d590}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x04000000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x2ac7ab20}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x02000000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x558f5641}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x01000000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xab1eac83}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00800000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x563d5906}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00400000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xac7ab20c}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00200000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x58f56418}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00100000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xb1eac831}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00080000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x63d59063}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00040000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xc7ab20c7}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00020000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x8f56418f}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00010000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x1eac831e}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00008000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x3d59063c}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00004000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x7ab20c78}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00002000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xf56418f0}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00001000}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xeac831e1}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000800}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xd59063c2}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000400}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xab20c784}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000200}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x56418f09}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000100}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xac831e12}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000080}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x59063c25}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000040}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xb20c784b}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000020}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x6418f097}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000010}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0xc831e12f}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000008}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x9063c25f}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000004}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x20c784be}, - {0xbf, 5, 3, 0, 0x00000000}, - {0x57, 5, 0, 0, 0x00000002}, - {0x15, 5, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x418f097c}, - {0x57, 3, 0, 0, 0x00000001}, - {0x15, 3, 0, 1, 0x00000000}, - {0xa7, 4, 0, 0, 0x831e12f9}, - {0xbf, 5, 1, 0, 0x00000000}, - {0x67, 5, 0, 0, 0x00000020}, - {0xc7, 5, 0, 0, 0x00000020}, - {0xbf, 3, 4, 0, 0x00000000}, - {0xa7, 3, 0, 0, 0x063c25f3}, - {0x6d, 2, 5, 1, 0x00000000}, - {0xbf, 3, 4, 0, 0x00000000}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x40000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x0c784be7}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x20000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x18f097cf}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x10000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x31e12f9f}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x08000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x63c25f3f}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x04000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xc784be7f}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x02000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x8f097cff}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x01000000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x1e12f9fe}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00800000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x3c25f3fc}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00400000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x784be7f8}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00200000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xf097cff0}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00100000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xe12f9fe0}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00080000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xc25f3fc1}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00040000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x84be7f83}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00020000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x097cff07}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00010000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x12f9fe0f}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00008000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x25f3fc1f}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00004000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x4be7f83f}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00002000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x97cff07f}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00001000}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x2f9fe0fe}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000800}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x5f3fc1fd}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000400}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xbe7f83fb}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000200}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x7cff07f7}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000100}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xf9fe0fee}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000080}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xf3fc1fdc}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000040}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xe7f83fb8}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000020}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xcff07f70}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000010}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x9fe0fee1}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000008}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x3fc1fdc2}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000004}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0x7f83fb85}, - {0xbf, 2, 1, 0, 0x00000000}, - {0x57, 2, 0, 0, 0x00000002}, - {0x15, 2, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xff07f70a}, - {0x57, 1, 0, 0, 0x00000001}, - {0x15, 1, 0, 1, 0x00000000}, - {0xa7, 3, 0, 0, 0xfe0fee15}, - {0x71, 1, 0, 201, 0x00000000}, - {0x67, 1, 0, 0, 0x00000008}, - {0x71, 2, 0, 200, 0x00000000}, - {0x4f, 1, 2, 0, 0x00000000}, - {0x71, 2, 0, 202, 0x00000000}, - {0x67, 2, 0, 0, 0x00000010}, - {0x71, 4, 0, 203, 0x00000000}, - {0x67, 4, 0, 0, 0x00000018}, - {0x4f, 4, 2, 0, 0x00000000}, - {0x4f, 4, 1, 0, 0x00000000}, - {0x67, 3, 0, 0, 0x00000020}, - {0x77, 3, 0, 0, 0x00000020}, - {0x9f, 3, 4, 0, 0x00000000}, - {0x57, 3, 0, 0, 0x0000000f}, - {0x67, 3, 0, 0, 0x00000002}, - {0x0f, 0, 3, 0, 0x00000000}, - {0x71, 1, 0, 137, 0x00000000}, - {0x67, 1, 0, 0, 0x00000008}, - {0x71, 2, 0, 136, 0x00000000}, - {0x4f, 1, 2, 0, 0x00000000}, - {0x71, 2, 0, 138, 0x00000000}, - {0x67, 2, 0, 0, 0x00000010}, - {0x71, 3, 0, 139, 0x00000000}, - {0x67, 3, 0, 0, 0x00000018}, - {0x4f, 3, 2, 0, 0x00000000}, - {0x4f, 3, 1, 0, 0x00000000}, - {0x07, 3, 0, 0, 0x7cafe800}, - {0x63, 6, 3, 52, 0x00000000}, - {0xb7, 7, 0, 0, 0x00000001}, - {0xbf, 0, 7, 0, 0x00000000}, - {0x95, 0, 0, 0, 0x00000000}, -}; From patchwork Mon Apr 8 21:18:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 139198 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id AA4E943DD2; Mon, 8 Apr 2024 23:25:44 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4B40140A8A; Mon, 8 Apr 2024 23:24:55 +0200 (CEST) Received: from mail-pf1-f174.google.com (mail-pf1-f174.google.com [209.85.210.174]) by mails.dpdk.org (Postfix) with ESMTP id B6736406BA for ; Mon, 8 Apr 2024 23:24:49 +0200 (CEST) Received: by mail-pf1-f174.google.com with SMTP id d2e1a72fcca58-6ecfeefe94cso2338502b3a.0 for ; Mon, 08 Apr 2024 14:24:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712611489; x=1713216289; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BtpPRaPty+0Dd8cf0lCOP8QlzleEFDjQWmR04lLhceU=; b=W88rNUP9A2Vibp7/QucFQ2vNUPqX2E3SfOSRQC+J1/aNB+bASPRAKwS7OTS2AUWhfi tlK9xVuqHAgKWw4kRMKP39ADEc3M/v7f40QnE0z/p8zEyWri6BeSyXu3+AhlonRom8uy QilwcdBwZYRWyepFIH/BQme68jzq4sENP8afFFFYs9EFQMN3GLC75DtkslkNgvnQrPeV IJeMI5p5XnBP2btRpJytdjg472lzCLMUgMq7FU876yX8XMcDhAq41NctHVD5vTnNWu6L PtZ/EDHSN1sl+FMRUG4U7KeO+K5kdM1NBKmOfLN9VgyQj3/32WPWFonSa6mewu3cyIeL F63g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712611489; x=1713216289; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BtpPRaPty+0Dd8cf0lCOP8QlzleEFDjQWmR04lLhceU=; b=YdopvjSOcsZ8QvvjOi1wSKtEr+YnLZOUIhpJnr6RXQ3qLN8cvhDEBqSCe+QupUBoZ8 yNMGJS8NbJHzMjpUhjfJSkjg1IBjYpBEg5Cd7f9jIKzjWQUzRGIwJwb/5+suKlIopW0j 8IDVqa8MYdn0U1w6bwLtLEodkStGtjYj441sTlyAHlliS/+j3CbhSPMgRQbtdF7vjBLP fr3bQgmv8w09vPXZDEJSrGptb8CKgUgb6uSwHNMBN56zhhPQXc37DCtNHpoxzyqMc5PP rMX0ZvIraBBtx+c+eAnF6aBh6gDhkj+m6HSv3M5z5jdV6qZjzUXT+KW83C4GvlxKv8DQ x5Pw== X-Gm-Message-State: AOJu0YywVXO8vlz7IX2b6UEgRFjsovcJfkit3PcOlgJS3JLbC9oqlKGs xdXKq/CZSbOnWOL8Ocjtxk8CuXpY5SPLXq2yYOjaEJSQfzHwKKSIjcaZox6tVtsSJBVyDbrvZoR aWW4= X-Google-Smtp-Source: AGHT+IGvTpY8xzXTdjAkhyVi/40K60R0gBqkQ6d4F4jFy2EWunLNU2B7s8JpFml1rsaijcNZ9JEUxQ== X-Received: by 2002:a05:6a21:3e0d:b0:1a3:a58a:5f77 with SMTP id bk13-20020a056a213e0d00b001a3a58a5f77mr1128426pzc.22.1712611488713; Mon, 08 Apr 2024 14:24:48 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id f16-20020a633810000000b005e43cce33f8sm6924725pga.88.2024.04.08.14.24.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Apr 2024 14:24:48 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v7 8/8] doc: update documentation of TAP PMD Date: Mon, 8 Apr 2024 14:18:39 -0700 Message-ID: <20240408212438.414099-9-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240408212438.414099-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240408212438.414099-1-stephen@networkplumber.org> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The driver support of flows has changed and the wording in the guide was awkward. Drop references to DPDK pktgen in this documentation since it is not required and confusing. Signed-off-by: Stephen Hemminger --- doc/guides/linux_gsg/sys_reqs.rst | 3 + doc/guides/nics/tap.rst | 268 ++++++++---------------------- 2 files changed, 74 insertions(+), 197 deletions(-) diff --git a/doc/guides/linux_gsg/sys_reqs.rst b/doc/guides/linux_gsg/sys_reqs.rst index 13be715933..0254568517 100644 --- a/doc/guides/linux_gsg/sys_reqs.rst +++ b/doc/guides/linux_gsg/sys_reqs.rst @@ -101,6 +101,9 @@ Running DPDK Applications To run a DPDK application, some customization may be required on the target machine. +.. _linux_gsg_kernel_version: + + System Software ~~~~~~~~~~~~~~~ diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst index d4f45c02a1..7f07c68808 100644 --- a/doc/guides/nics/tap.rst +++ b/doc/guides/nics/tap.rst @@ -1,47 +1,45 @@ .. SPDX-License-Identifier: BSD-3-Clause Copyright(c) 2016 Intel Corporation. -Tun|Tap Poll Mode Driver -======================== +TAP Poll Mode Driver +==================== -The ``rte_eth_tap.c`` PMD creates a device using TAP interfaces on the -local host. The PMD allows for DPDK and the host to communicate using a raw -device interface on the host and in the DPDK application. +The TAP Poll Mode Driver (PMD) is a virtual device for injecting packets to be processed +by the Linux kernel. This PMD is useful when writing DPDK application +for offloading network functionality (such as tunneling) from the kernel. -The device created is a TAP device, which sends/receives packet in a raw -format with a L2 header. The usage for a TAP PMD is for connectivity to the -local host using a TAP interface. When the TAP PMD is initialized it will -create a number of tap devices in the host accessed via ``ifconfig -a`` or -``ip`` command. The commands can be used to assign and query the virtual like -device. +From the kernel point of view, the TAP device looks like a regular network interface. +The network device can be managed by standard tools such as ``ip`` and ``ethtool`` commands. +It is also possible to use existing packet tools such as ``wireshark`` or ``tcpdump``. -These TAP interfaces can be used with Wireshark or tcpdump or Pktgen-DPDK -along with being able to be used as a network connection to the DPDK -application. The method enable one or more interfaces is to use the -``--vdev=net_tap0`` option on the DPDK application command line. Each -``--vdev=net_tap1`` option given will create an interface named dtap0, dtap1, -and so on. +From the DPDK application, the TAP device looks like a DPDK ethdev. +Packets are sent and received in L2 (Ethernet) format. The standare DPDK +API's to query for information, statistics and send and receive packets +work as expected. -The interface name can be changed by adding the ``iface=foo0``, for example:: + +Arguments +--------- + +TAP devices are created with the command line +``--vdev=net_tap0`` option. This option maybe specified more the once by repeating +with a different ``net_tapX`` device. + +By default, the Linux interfaces are named ``dtap0``, ``dtap1``, etc. +The interface name can be specified by adding the ``iface=foo0``, for example:: --vdev=net_tap0,iface=foo0 --vdev=net_tap1,iface=foo1, ... -Normally the PMD will generate a random MAC address, but when testing or with -a static configuration the developer may need a fixed MAC address style. -Using the option ``mac=fixed`` you can create a fixed known MAC address:: +Normally the PMD will generate a random MAC address. +If a static address is desired instead, the ``mac=fixed`` can be used. --vdev=net_tap0,mac=fixed -The MAC address will have a fixed value with the last octet incrementing by one -for each interface string containing ``mac=fixed``. The MAC address is formatted -as 02:'d':'t':'a':'p':[00-FF]. Convert the characters to hex and you get the -actual MAC address: ``02:64:74:61:70:[00-FF]``. - - --vdev=net_tap0,mac="02:64:74:61:70:11" +With the fixed option, the MAC address will have the first octets: +as 02:'d':'t':'a':'p':[00-FF] and the last octets are the interface number. -The MAC address will have a user value passed as string. The MAC address is in -format with delimiter ``:``. The string is byte converted to hex and you get -the actual MAC address: ``02:64:74:61:70:11``. +To specify a specific MAC address use the conventional representation. +The string is byte converted to hex, the result is MAC address: ``02:64:74:61:70:11``. It is possible to specify a remote netdevice to capture packets from by adding ``remote=foo1``, for example:: @@ -59,40 +57,20 @@ netdevice that has no support in the DPDK. It is possible to add explicit rte_flow rules on the tap PMD to capture specific traffic (see next section for examples). -After the DPDK application is started you can send and receive packets on the -interface using the standard rx_burst/tx_burst APIs in DPDK. From the host -point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen -and others to communicate with the DPDK application. The DPDK application may -not understand network protocols like IPv4/6, UDP or TCP unless the -application has been written to understand these protocols. - -If you need the interface as a real network interface meaning running and has -a valid IP address then you can do this with the following commands:: - - sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0 - sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1 - -Please change the IP addresses as you see fit. - -If routing is enabled on the host you can also communicate with the DPDK App -over the internet via a standard socket layer application as long as you -account for the protocol handling in the application. - -If you have a Network Stack in your DPDK application or something like it you -can utilize that stack to handle the network protocols. Plus you would be able -to address the interface using an IP address assigned to the internal -interface. - Normally, when the DPDK application exits, the TAP device is marked down and is removed. -But this behaviour can be overridden by the use of the persist flag, example:: +But this behavior can be overridden by the use of the persist flag, example:: --vdev=net_tap0,iface=tap0,persist ... -The TUN PMD allows user to create a TUN device on host. The PMD allows user -to transmit and receive packets via DPDK API calls with L3 header and payload. -The devices in host can be accessed via ``ifconfig`` or ``ip`` command. TUN -interfaces are passed to DPDK ``rte_eal_init`` arguments as ``--vdev=net_tunX``, +TUN devices +----------- + +The TAP device can be used an L3 tunnel only device (TUN). +This type of device does not include the Ethernet (L2) header; all packets +are sent and received as IP packets. + +TUN device are creted with the command line arguments as ``--vdev=net_tunX``, where X stands for unique id, example:: --vdev=net_tun0 --vdev=net_tun1,iface=foo1, ... @@ -103,27 +81,33 @@ options. Default interface name is ``dtunX``, where X stands for unique id. Flow API support ---------------- -The tap PMD supports major flow API pattern items and actions, when running on -linux kernels above 4.2 ("Flower" classifier required). -The kernel support can be checked with this command:: +The TAP PMD supports major flow API pattern items and actions. + +Requirements +~~~~~~~~~~~~ - zcat /proc/config.gz | ( grep 'CLS_FLOWER=' || echo 'not supported' ) | - tee -a /dev/stderr | grep -q '=m' && - lsmod | ( grep cls_flower || echo 'try modprobe cls_flower' ) +Flow support in TAP driver requires the Linux flow based traffic control filter +``flower``. This was added in Linux 4.3 kernel. -Supported items: +The implementation of RSS action uses an eBPF module that requires additional +libraries and tools. Building the RSS support requires the ``clang`` +compiler to compile the C code to BPF target; ``bpftool`` to convert the +compiled BPF object to a header file; and ``libbpf`` to load the eBPF +action into the kernel. -- eth: src and dst (with variable masks), and eth_type (0xffff mask). -- vlan: vid, pcp, but not eid. (requires kernel 4.9) -- ipv4/6: src and dst (with variable masks), and ip_proto (0xffff mask). -- udp/tcp: src and dst port (0xffff) mask. +Supported match items: + + - eth: src and dst (with variable masks), and eth_type (0xffff mask). + - vlan: vid, pcp, but not eid. (requires kernel 4.9) + - ipv4/6: src and dst (with variable masks), and ip_proto (0xffff mask). + - udp/tcp: src and dst port (0xffff) mask. Supported actions: - DROP - QUEUE - PASSTHRU -- RSS (requires kernel 4.9) +- RSS It is generally not possible to provide a "last" item. However, if the "last" item, once masked, is identical to the masked spec, then it is supported. @@ -133,7 +117,7 @@ full mask (exact match). As rules are translated to TC, it is possible to show them with something like:: - tc -s filter show dev tap1 parent 1: + tc -s filter show dev dtap1 parent 1: Examples of testpmd flow rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -174,135 +158,25 @@ The IPC synchronization of Rx/Tx queues is currently limited: - Maximum 8 queues shared - Synchronized on probing, but not on later port update -Example -------- - -The following is a simple example of using the TAP PMD with the Pktgen -packet generator. It requires that the ``socat`` utility is installed on the -test system. - -Build DPDK, then pull down Pktgen and build pktgen using the DPDK SDK/Target -used to build the dpdk you pulled down. - -Run pktgen from the pktgen directory in a terminal with a commandline like the -following:: - - sudo ./app/app/x86_64-native-linux-gcc/app/pktgen -l 1-5 -n 4 \ - --proc-type auto --log-level debug --socket-mem 512,512 --file-prefix pg \ - --vdev=net_tap0 --vdev=net_tap1 -b 05:00.0 -b 05:00.1 \ - -b 04:00.0 -b 04:00.1 -b 04:00.2 -b 04:00.3 \ - -b 81:00.0 -b 81:00.1 -b 81:00.2 -b 81:00.3 \ - -b 82:00.0 -b 83:00.0 -- -T -P -m [2:3].0 -m [4:5].1 \ - -f themes/black-yellow.theme - -.. Note: - - Change the ``-b`` options to exclude all of your physical ports. The - following command line is all one line. - - Also, ``-f themes/black-yellow.theme`` is optional if the default colors - work on your system configuration. See the Pktgen docs for more - information. - -Verify with ``ifconfig -a`` command in a different xterm window, should have a -``dtap0`` and ``dtap1`` interfaces created. - -Next set the links for the two interfaces to up via the commands below:: - - sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0 - sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1 - -Then use socat to create a loopback for the two interfaces:: - - sudo socat interface:dtap0 interface:dtap1 - -Then on the Pktgen command line interface you can start sending packets using -the commands ``start 0`` and ``start 1`` or you can start both at the same -time with ``start all``. The command ``str`` is an alias for ``start all`` and -``stp`` is an alias for ``stop all``. - -While running you should see the 64 byte counters increasing to verify the -traffic is being looped back. You can use ``set all size XXX`` to change the -size of the packets after you stop the traffic. Use pktgen ``help`` -command to see a list of all commands. You can also use the ``-f`` option to -load commands at startup in command line or Lua script in pktgen. RSS specifics ------------- -Packet distribution in TAP is done by the kernel which has a default -distribution. This feature is adding RSS distribution based on eBPF code. -The default eBPF code calculates RSS hash based on Toeplitz algorithm for -a fixed RSS key. It is calculated on fixed packet offsets. For IPv4 and IPv6 it -is calculated over src/dst addresses (8 or 32 bytes for IPv4 or IPv6 -respectively) and src/dst TCP/UDP ports (4 bytes). - -The RSS algorithm is written in file ``tap_bpf_program.c`` which -does not take part in TAP PMD compilation. Instead this file is compiled -in advance to eBPF object file. The eBPF object file is then parsed and -translated into eBPF byte code in the format of C arrays of eBPF -instructions. The C array of eBPF instructions is part of TAP PMD tree and -is taking part in TAP PMD compilation. At run time the C arrays are uploaded to -the kernel via BPF system calls and the RSS hash is calculated by the -kernel. - -It is possible to support different RSS hash algorithms by updating file -``tap_bpf_program.c`` In order to add a new RSS hash algorithm follow these -steps: - -#. Write the new RSS implementation in file ``tap_bpf_program.c`` - - BPF programs which are uploaded to the kernel correspond to - C functions under different ELF sections. - -#. Install ``LLVM`` library and ``clang`` compiler versions 3.7 and above - -#. Use make to compile `tap_bpf_program.c`` via ``LLVM`` into an object file - and extract the resulting instructions into ``tap_bpf_insn.h``:: - - cd bpf; make - -#. Recompile the TAP PMD. - -The C arrays are uploaded to the kernel using BPF system calls. - -``tc`` (traffic control) is a well known user space utility program used to -configure the Linux kernel packet scheduler. It is usually packaged as -part of the ``iproute2`` package. -Since commit 11c39b5e9 ("tc: add eBPF support to f_bpf") ``tc`` can be used -to uploads eBPF code to the kernel and can be patched in order to print the -C arrays of eBPF instructions just before calling the BPF system call. -Please refer to ``iproute2`` package file ``lib/bpf.c`` function -``bpf_prog_load()``. - -An example utility for eBPF instruction generation in the format of C arrays will -be added in next releases - -TAP reports on supported RSS functions as part of dev_infos_get callback: -``RTE_ETH_RSS_IP``, ``RTE_ETH_RSS_UDP`` and ``RTE_ETH_RSS_TCP``. -**Known limitation:** TAP supports all of the above hash functions together -and not in partial combinations. - -Systems supporting flow API ---------------------------- - -- "tc flower" classifier requires linux kernel above 4.2 -- eBPF/RSS requires linux kernel above 4.9 - -+--------------------+-----------------------+ -| RH7.3 | No flow rule support | -+--------------------+-----------------------+ -| RH7.4 | No RSS action support | -+--------------------+-----------------------+ -| RH7.5 | No RSS action support | -+--------------------+-----------------------+ -| SLES 15, | No limitation | -| kernel 4.12 | | -+--------------------+-----------------------+ -| Azure Ubuntu 16.04,| No limitation | -| kernel 4.13 | | -+--------------------+-----------------------+ +The default packet distribution in TAP without flow rules is done by the +kernel which has a default flow based distribution. +When flow rules are used to distribute packets across a set of queues +an eBPF program is used to calculate the RSS based on Toeplitz algorithm for +with the given key. + +The hash is calculated for IPv4 and IPv6, over src/dst addresses +(8 or 32 bytes for IPv4 or IPv6 respectively) and +optionally the src/dst TCP/UDP ports (4 bytes). + Limitations ----------- -* Rx/Tx must have the same number of queues. +- Since TAP device uses a file descriptors to talk to the kernel. + The same number of queues must be specified for receive and transmit. + +- The RSS algorithm only support L3 or L4 functions. It does not support + finer grain selections (for example: only IPV6 packets with extension headers).