From patchwork Tue Apr 2 17:12: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: 139023 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 54A6F43DC3; Tue, 2 Apr 2024 19:18:00 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7D6AA402E4; Tue, 2 Apr 2024 19:17:56 +0200 (CEST) Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) by mails.dpdk.org (Postfix) with ESMTP id A7F764021F for ; Tue, 2 Apr 2024 19:17:54 +0200 (CEST) Received: by mail-pf1-f173.google.com with SMTP id d2e1a72fcca58-6e6afb754fcso5155676b3a.3 for ; Tue, 02 Apr 2024 10:17:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712078274; x=1712683074; 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=wZN6PQ8+YIarfHwVQyRsvAP7foAvlLKbOQ2Ca9kys3TyngfYHjHIYXJ2p4vpYicHn/ ZxXbO2eaUMwdzHbg0V7KozcxlcmkEZ691HpBM0jl1I1iAzgzMVgT+vjKSbNmImf+pFun GV9lD356fLiaEhA6hSCooMm/kvBlz2RsGMLW/KwjH6ioqbv2KuDeABkNKTPqUdWpWN6c JWw3C4yrVV4dlQHBe4nUXqgtWS18V+RCHNHW9LbXzAVhKVn58TT05L4GspZDAh4zmAPz o/fVEaxGGCFR8CwwQzK7XbBMc00PrWcA5wRBQIH7oOCJEgWmV2N943LEd3q8iONpup1J 5g+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712078274; x=1712683074; 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=AA+YpwR2IQ+7B88d38mHtJ4WkKfYpjn/eA379pPcb7xP0ZAck4iKLCCnPmIkPma0Jz UkBKcK35F4wtucCHvmFr6/wloX1pa7vpcVyaHfdHFQjrZu8Wb0uEK2hOdJbeo5yne1vw bYI9NljvkTYWHV4jaBVFgnUrAXr43XfW/pEdXycV8epFNoyl7FaO+XXtWXaioMHZonK6 1cNL5rw5HB88TECt90akl+XxVb0hNe7VSO9FFnKcwATQhLE3SBbg4EXgYxMyeECyUJHM 443ja+AAo1/tktdEwlHQ1UJFptUiSkgkL8Z1P8dkU/64RHDlQUKDbUMmUroRlt9GLJ98 +vyw== X-Gm-Message-State: AOJu0YyyWF675Ifiq8vplS2MdVTesGR1/b3xavduCDxS02JwnoACylKn dJ4KNIk1OYFvnQjzqxXwo9ssuKwEKJgYDuwY7xP/shE66uKkXAqHAaxOieW+BzP21GUPAXRO8gI E X-Google-Smtp-Source: AGHT+IGfHV41HhYvu0CSnrDILkCwH4BURlIazVz8+JSujB7+01iPSxiCbYTBHzaFvibX6txkjD8ojw== X-Received: by 2002:a05:6a20:d90f:b0:1a7:c2b:5dc6 with SMTP id jd15-20020a056a20d90f00b001a70c2b5dc6mr11530814pzb.28.1712078273812; Tue, 02 Apr 2024 10:17:53 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id q15-20020a170902a3cf00b001e264b50964sm2219815plb.205.2024.04.02.10.17.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 10:17:53 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v5 1/8] net/tap: do not duplicate fd's Date: Tue, 2 Apr 2024 10:12:33 -0700 Message-ID: <20240402171751.138324-2-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240402171751.138324-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240402171751.138324-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 Tue Apr 2 17:12: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: 139024 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 66CBD43DC3; Tue, 2 Apr 2024 19:18:10 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2C4814064C; Tue, 2 Apr 2024 19:17:58 +0200 (CEST) Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) by mails.dpdk.org (Postfix) with ESMTP id 5F437402D8 for ; Tue, 2 Apr 2024 19:17:55 +0200 (CEST) Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-1e244c7cbf8so22859885ad.0 for ; Tue, 02 Apr 2024 10:17:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712078274; x=1712683074; 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=zxIUf5LqWFYk0J3FN48Qroz1rnjdL/+cKWhdS8rBBwc=; b=HqGxdJjX1uS1Va7nMdT9tWeUoZDXz2SaRWyEy8kaPrN+3RDzIjDsz56mUm22rA2zcf P3ZsNgMmk0pYQjGladSWZlyLMW4mm12rgo1otLwa55Btw9UkL6OGUXripjVlMvk3p1ap xGuyCk0V5NRK/welkzivlJtMaAZnhtizgfX/hDjpwAyYyjXJvLG+WlG+gPf8BjIxKjII 4/PiPUWdYENnnIPOKm8eW4DGcsRE4jpuu2DdqCmai3QkqHA086NGzJuUg855ck9ZBN2Y Y91cnky3VofJ+drEC9DW+qQGxkQnwxrCJ1ytleUPm56Urqeo3Vkh5qMPq/YiZc4IWJqc TaQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712078274; x=1712683074; 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=zxIUf5LqWFYk0J3FN48Qroz1rnjdL/+cKWhdS8rBBwc=; b=Vy3O78q0eejZc8AETkBsdh0BFByXSqNgSLbLApsnC+tWFiF3xi0zhjqdz4Idpo+9Gd 9i56KaXhSQJJRrxpHdQCDMjet9FRZ0QmZa0+WXeCuc3CSj/4WWaKZshItE/At1GPaT1D 6ZQDyjnbIQ9MhVLcE/q9aOVrO71O0LoTtjTgw57tiVA7PbjeKnzCKupk3xtWgcNBR901 Eu39wXF3plfTBs+XPHPFYc5Zp0RzHrB9zYeQYjsJ0LH0/pF8EOCBtfg8fqrkUwm7Zcby rGyvUnAcEKJX7WS1Zq7wpfoOS9HZhXf4jZwzxT1Rjn8eG8ui1kzRjcjal0zVpnhmOvI+ R6Dg== X-Gm-Message-State: AOJu0YwLbMMCwhfYYPNiHmujjKR6S9AkaAAlzdQ+VZ6Oy4/23a7itZbZ 30cdKpS1giZuoiBURRG/aEV7xkRydqKiimAKwYqkZJybfDQv86ZqrpiDnYNO+49yvFzQhe4V9ah V X-Google-Smtp-Source: AGHT+IEZlEdPdcc/rSAQv0cBc2FAZ74Fa2EwHAGx5Hq821kL6XosTPkYQ15JGW5C8JkUzxAOlVW6fA== X-Received: by 2002:a17:902:654d:b0:1dd:e15e:4a5a with SMTP id d13-20020a170902654d00b001dde15e4a5amr385595pln.59.1712078274462; Tue, 02 Apr 2024 10:17:54 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id q15-20020a170902a3cf00b001e264b50964sm2219815plb.205.2024.04.02.10.17.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 10:17:54 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v5 2/8] doc: fix the requirements and building of TAP flow Date: Tue, 2 Apr 2024 10:12:34 -0700 Message-ID: <20240402171751.138324-3-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240402171751.138324-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240402171751.138324-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 build process for TAP eBPF RSS is now changed, so documentation needs to be updated. Since kernel 4.19 is the oldest current LTS supported kernel, the TAP documentation can be simplified. Any complaints about flow not working means the kernel is out of scope of current DPDK. Signed-off-by: Stephen Hemminger --- doc/guides/linux_gsg/sys_reqs.rst | 3 + doc/guides/nics/tap.rst | 95 ++++++++----------------------- 2 files changed, 28 insertions(+), 70 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..dcfefba567 100644 --- a/doc/guides/nics/tap.rst +++ b/doc/guides/nics/tap.rst @@ -103,13 +103,8 @@ 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:: - 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' ) +The tap PMD supports major flow API pattern items and actions, when running on a supported Linux version. See :ref:`linux_gsg_kernel_version`. Supported items: @@ -123,7 +118,7 @@ Supported actions: - DROP - QUEUE - PASSTHRU -- RSS (requires kernel 4.9) +- RSS (requires clang, libbpf, and bpftool) 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. @@ -229,80 +224,40 @@ 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 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 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. +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). -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 +The RSS algorithm is written in file ``tap_rss.c`` which is compiled with +clang and then turned into a skeleton header file with bpftool. +The skeleton header file is then compiled into the tap driver. 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. + +**Known limitation:** TAP supports only these functions, it is not possible +to be more fine grained. For example, selecting only IPv4 and not IPV6 +to be hashed is not possible. 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 | | -+--------------------+-----------------------+ +- Any system which meets the current DPDK kernel requirements should + be able to support the flow API. + +- Supporting eBPF/RSS requires ``bpftool`` and ``libbpf``. Limitations ----------- * Rx/Tx must have the same number of queues. + +* The kernel will distribute packets across all queues. + If using flow API then add a default match and action to force a different + behavior. From patchwork Tue Apr 2 17:12: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: 139025 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 67A6D43DC3; Tue, 2 Apr 2024 19:18:17 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 59A03402EA; Tue, 2 Apr 2024 19:17:59 +0200 (CEST) Received: from mail-pl1-f182.google.com (mail-pl1-f182.google.com [209.85.214.182]) by mails.dpdk.org (Postfix) with ESMTP id E5C2B402DD for ; Tue, 2 Apr 2024 19:17:55 +0200 (CEST) Received: by mail-pl1-f182.google.com with SMTP id d9443c01a7336-1dff837d674so42480225ad.3 for ; Tue, 02 Apr 2024 10:17:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712078275; x=1712683075; 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=Y6IpP5zvxIujmFtOh3sV0ft7EWj0kxJrwStvA0odNiU=; b=dj0nghhUt5dM8XgK2uScKT7teFwxBkmV0Y/UF1BZHd3L97loT72frFOPXb2aqkDszZ AtP5OE4gz6sgZRe5+7zgnhNiK5X8WpgB4l8i1VLH1JHvQeBcsgSY8OrKIYjsPvHNNJhc AW9jSmwo19jJdfms1iAjslFfqKjW4i5k5Q3O5UIDqzpoNnibpegfV7I3nZxTud3W9KA5 NkWDsgjj3WxchDiZOrpZoR3+BJaPLCCFYRX0kafvdBrI4vMTODDuKi89p4S1JZBr3FI9 iJo20Ioe1yQcAErV+9+C7+8pp6WtYWTectQPddkttXj5hUhyDvjmtYFJ3V0eiXUBat2x JUvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712078275; x=1712683075; 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=Y6IpP5zvxIujmFtOh3sV0ft7EWj0kxJrwStvA0odNiU=; b=qhlS8ZB5d+GwnU93v1UpPyR1ET74f3hBf7q+FwVBjgOuJ8hxElO7xhZYnx8ZZFBZse vkx6EwNlTLjU1KSGx6i0XT0PnKf7VwTMAvvOcZuowk+zENVV7vNmKTQbEmpfw2XnKQJl QzT2lYjDvqcoBQspWSHXnd0Y8p3uiywrlGHZDpDlUtPSkTthhib9+njZt/UKZ4sH3wX2 dfbHl+HeREG2qtHSvPVySWl+g/KaZ0ddDMAlVPFk94Xv05ViWvsaQgISsA7MFMrfXYTv NjzTdTCC4qSWuwQ9T6ctO0d5W0WEpaxlLNaHmPQgMR3rm2TlbPWQiNlbFLguR6q+1dGO SRFw== X-Gm-Message-State: AOJu0YyygiNWs0/lR/2N/D9haLIGfErGNQr89I6rzA0Nz9K9JugT1XAG DdBI/oFHLladFwjk5nk20uQmzWKWEVtVjxp9gEKR4Jnc9ODu1AhI71xZ2jQVS8MNvJsDyNRKLru u X-Google-Smtp-Source: AGHT+IEZc8x9bj8JnAJCBdZ2JfaD0+RKRzjKx+gKgWCRtHMqzaRDKS+WA8yzEOI7p4Ue+PhazL8HjQ== X-Received: by 2002:a17:902:8645:b0:1e2:1df:449b with SMTP id y5-20020a170902864500b001e201df449bmr12983171plt.69.1712078275125; Tue, 02 Apr 2024 10:17:55 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id q15-20020a170902a3cf00b001e264b50964sm2219815plb.205.2024.04.02.10.17.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 10:17:54 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v5 3/8] net/tap: remove unused RSS hash types Date: Tue, 2 Apr 2024 10:12:35 -0700 Message-ID: <20240402171751.138324-4-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240402171751.138324-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240402171751.138324-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. Signed-off-by: Stephen Hemminger --- drivers/net/tap/tap_rss.h | 6 ------ 1 file changed, 6 deletions(-) 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 Tue Apr 2 17:12:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 139026 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 C6FBB43DC3; Tue, 2 Apr 2024 19:18:24 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7F56A402F2; Tue, 2 Apr 2024 19:18:00 +0200 (CEST) Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) by mails.dpdk.org (Postfix) with ESMTP id 68BA2402EA for ; Tue, 2 Apr 2024 19:17:57 +0200 (CEST) Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-1e220e40998so29849285ad.1 for ; Tue, 02 Apr 2024 10:17:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712078276; x=1712683076; 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=bMIs8byUpUidcCsPv/WiBxm0KoKna2m6Th8YamB9fiM=; b=l3Y4x9JbXP063T8lFTqxjdBE3zD4Wrkz3h7YdZAnggypaU+Oh2vcy2NNHs4064paUj qeKS0GC92SDnPiXt4b1YbkNMdS+CEvRPl98293TpbnwIzGc7irezzjOfoFzGAtKQZwXW coTk9La7ANrS5X8p3cMJtgKL0JDGMdxBhDgKMetVNK75eV0nLV8eMQDYtICypZygcG0K 5fPVd2EwCuENOM5iqED0JBmAK3UU76V2gHpjCLWDuyRBS7XsNCdXgfbftzOezaB2Qw9w kdsiv9j4cSVCIYvyqxH5hdGNH1JJVqRVqjvNmNnn9X3fso2I49slSkUO7V4t6OcFfX5X qBWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712078276; x=1712683076; 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=bMIs8byUpUidcCsPv/WiBxm0KoKna2m6Th8YamB9fiM=; b=tBsb3NB/0H7TyvcrTjLVePzvxPaHLGEXKCBzhob9AhRWCCMHEb4bMY8D9gx1HUtAwz AyBkhoVtKvdJF56HgZLu+ymkzKwXuoHHnH46y+w6sp+svgKeBlfuDCO0u0Wna7pwkK06 afg2i59QKy93GKkWU4UlVO6hE/BbbQ1wtmEGl+1e5N4vxuWefwb45LLUuDEBX/peB1CU 03nzcF7M89tYzwdmqs57c1oW/c7ewaBv9BC2sWeKTPjgJRRX3/b7uThFPTrGK93hbTGG D4eOgVV83J6Snxl4kKtZtGSGgRBf+58KP54SPUV7jNGPl0kP0qYmXDxElcV2rVMtY8U2 m9ZA== X-Gm-Message-State: AOJu0Yyp5uotnLpzs7sm06hx817yQw1vfybKxz12NGpE1sVmErq85zZE pGFMOQsQM2fRjv2jgxNoNSw8JDUrf5u85/KR/OdwjcxU6daqGa5i+3rpQ78f9fmcbrjkZ1IMP+3 L X-Google-Smtp-Source: AGHT+IHApKI5CK+lEezhYWWagordE4fy6rvuHYHw7yvHc/n8SjCpZCdHsMgMFQVtf9RZjxC5QmW90g== X-Received: by 2002:a17:902:ced0:b0:1e2:73a9:7fb0 with SMTP id d16-20020a170902ced000b001e273a97fb0mr339737plg.18.1712078276657; Tue, 02 Apr 2024 10:17:56 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id q15-20020a170902a3cf00b001e264b50964sm2219815plb.205.2024.04.02.10.17.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 10:17:55 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v5 4/8] net/tap: validate and setup parameters for BPF RSS Date: Tue, 2 Apr 2024 10:12:36 -0700 Message-ID: <20240402171751.138324-5-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240402171751.138324-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240402171751.138324-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 a78fd50cd4..7033e8411f 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 @@ -2062,6 +2064,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 * @@ -2080,11 +2097,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) @@ -2096,6 +2113,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) { @@ -2110,8 +2162,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 Tue Apr 2 17:12: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: 139027 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 DF56B43DC3; Tue, 2 Apr 2024 19:18:32 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 33D9D4068E; Tue, 2 Apr 2024 19:18:02 +0200 (CEST) Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) by mails.dpdk.org (Postfix) with ESMTP id 2B86D4064A for ; Tue, 2 Apr 2024 19:17:58 +0200 (CEST) Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-1e0411c0a52so45691845ad.0 for ; Tue, 02 Apr 2024 10:17:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712078277; x=1712683077; 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=fxMT1Q+dWMqhkfuzpplrDE8kvKhNXsbKAqFkf2RexRc=; b=TkaqciZ2jpH2s80QuimlTE1v6//tNkJMHuvBDgOIsfb3Pbe8J/fsIDJ2n6QgmR7E5G +tvTgkBdzFRXvFRHsPTHqyt80M+4Kd/CpqurBIf2YetAaY5Srl1Ee5B8QWlgSFsp980h r1n5Q58WwBaId0pKhuIrhn1OBGJlOOI3XZTgAjDQLCuoSpWCcVWdw2ITJRl1mhYFt1Fy j5EoSJKJmdu3UMzuDdqs+tW/ZblpunC+et2T9ze4trqpfEsezqaJ616c5G+CT6E4aZf/ 9Oh8D0emfRStfDPBx8AnylLrQtVeeKekuMrEaI0vN4HWNz5hB3Ah6FfYFkvT0wmUp2L2 pacg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712078277; x=1712683077; 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=fxMT1Q+dWMqhkfuzpplrDE8kvKhNXsbKAqFkf2RexRc=; b=P1LQclCYz254PUjv61G3xvZu4tNzNk92bb1tPaEHOVttivkPP4UVbq3ncgW7o9sGvc xHLGTAynBFT6cpx1Q1e7ONjifWfbXuZWCfUySy/KnduSQ0JJXT/2tVsqLwetZtwtW/1M qiJEWmnWzb24KWN/lkwySS716umzO7aMt5KEQqKAfzzDEV1dChGu+a3BegWOxl6KBqSg obcMioDBfUSpUGhMYqlDWcfDJbOK0AJ3HqM2Pvtgx4vGC2lUH2qdv8KxmIIR8UEwCk2K RO17jPJs+vF7Smi3YE0jfu1JfZY6vzBr6p4tCWgZK/SQ4yMeMxbqHO5JFPY6rVEBjwsv FoUw== X-Gm-Message-State: AOJu0Yw8b4pkHhN9lynuPtX3TL9/GLIEYRfV+HSjNrxrrn4S0f/781cz 9U/zAxm+Jutm0fwl8tsRKwT4oroSdldbfsp+jYkOR1bS+kh3rOjX1M8c64DZn0rexHEcsSrGJQU 5 X-Google-Smtp-Source: AGHT+IF/3olFrwQlXH8wSnJWwIt8uGfUKXP7SuI84/2VtJBinf+l7rtIfdzxuuqOOduVhxxjd6B3ZQ== X-Received: by 2002:a17:902:bcc2:b0:1e0:b9d0:f6b with SMTP id o2-20020a170902bcc200b001e0b9d00f6bmr9969938pls.68.1712078277340; Tue, 02 Apr 2024 10:17:57 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id q15-20020a170902a3cf00b001e264b50964sm2219815plb.205.2024.04.02.10.17.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 10:17:56 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v5 5/8] net/tap: stop "vendoring" linux bpf headers Date: Tue, 2 Apr 2024 10:12:37 -0700 Message-ID: <20240402171751.138324-6-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240402171751.138324-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240402171751.138324-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. This is not a supportable build method, and not how rest of DPDK works. Having own private (and divergent) version headers leads to future problems when BPF definitions evolve. Since DPDK officially supports only LTS or later kernel there is no need for the #ifdef workarounds in the TAP flow code. Cloning headers leads to problems and no longer needed. Signed-off-by: Stephen Hemminger --- drivers/net/tap/bpf/bpf_extract.py | 1 - drivers/net/tap/tap_bpf.h | 121 ----------------------------- drivers/net/tap/tap_bpf_api.c | 20 +++-- drivers/net/tap/tap_flow.c | 89 --------------------- 4 files changed, 13 insertions(+), 218 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/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_flow.c b/drivers/net/tap/tap_flow.c index 7033e8411f..e154ea0ae0 100644 --- a/drivers/net/tap/tap_flow.c +++ b/drivers/net/tap/tap_flow.c @@ -21,95 +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 { From patchwork Tue Apr 2 17:12:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 139028 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 2D3E043DC3; Tue, 2 Apr 2024 19:18:45 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id CEB80406B7; Tue, 2 Apr 2024 19:18:03 +0200 (CEST) Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) by mails.dpdk.org (Postfix) with ESMTP id 5D5CD4067C for ; Tue, 2 Apr 2024 19:17:59 +0200 (CEST) Received: by mail-pl1-f170.google.com with SMTP id d9443c01a7336-1e0411c0a52so45692065ad.0 for ; Tue, 02 Apr 2024 10:17:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712078278; x=1712683078; 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=Mhri9H8kS5gfjIMlY93FOne4N6sqvnB8a+SVEj6cbSyC/jirPF0HBPqnYhwZTvHYEA 6rU/PslEGFOYeE1AipD+Xi1USK6MyiOt8C2PCVUt5lTVD055WAaoE2njOwFJ9yAiKuHr 7wanQ673T4dtoEEgExvFH4I0EcXZfXFK34eYUFZJAP3uD8maX0w4Zh3ShD1yhqKGVYne FO0uyTohF5h9+hSGlWMqMm25G0ovhhBBuNq+zK238fpfJ6dpsRNGYw69mqInGYpprPP5 HylY4mCPPpppX6JnIye9oYOH7Sb0CHFw+7TvarnlG3cRW1CopZgvpxbfhrGGfXFrFhw9 4AeA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712078278; x=1712683078; 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=YiDU/W9IrVzCz/z88DwgZj6Hk/XIwM6pQd6GnMggc3Yv0mXANxyvAgBhYkzHRg7Zb9 MzdFOemu4ijdNL2cj3VGqjfK8Pbxj4omCcYfQKHROzjyGBoQI2NIxkWVCeb3mh30Ww9q 6TN7riCDEceQw34ZlFNCLb1/j8cpOL4taKbiFE/Hz5C2sLLPfGWd3dNnSOQ7kHv8nk9S p1QWXIPDGohNmMMPdGLSxmBT9uK7f0v+ASL9uANOoaFlHoLwn2kTMlKK5JVivgc78IKQ FO+xdncwCWHjfiQvOawI6QyoRyxMstRABBhMk60e2bHFRyP2c57nNQGQCNqx+QH6vW/p gC8g== X-Gm-Message-State: AOJu0YxZohUdAcu18prNUl781E0/onVxIGb/Kq5fF95WN+O+KT57QCPd 98fVUYdOiuoCsZ+npw6ekUxpIc1QR726uWbxqbtCEBOx8HqTHYketaBPxRQoZl275l+QZZTZZnC D X-Google-Smtp-Source: AGHT+IGtu1DHmIorTAzqvdOfJ5blZULq3yoLVS10SnHN8BIvNDE2AfpGvQifoN2Yg2PClTpoVLGMjg== X-Received: by 2002:a17:902:c947:b0:1e0:ca47:4d9b with SMTP id i7-20020a170902c94700b001e0ca474d9bmr13712268pla.29.1712078278256; Tue, 02 Apr 2024 10:17:58 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id q15-20020a170902a3cf00b001e264b50964sm2219815plb.205.2024.04.02.10.17.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 10:17:57 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v5 6/8] net/tap: rewrite the RSS BPF program Date: Tue, 2 Apr 2024 10:12:38 -0700 Message-ID: <20240402171751.138324-7-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240402171751.138324-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240402171751.138324-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 Tue Apr 2 17:12: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: 139029 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 C124043DC3; Tue, 2 Apr 2024 19:18:53 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1C959409FA; Tue, 2 Apr 2024 19:18:05 +0200 (CEST) Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) by mails.dpdk.org (Postfix) with ESMTP id 0D771402F2 for ; Tue, 2 Apr 2024 19:18:00 +0200 (CEST) Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-1e0878b76f3so757125ad.0 for ; Tue, 02 Apr 2024 10:17:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712078279; x=1712683079; 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=SlBVx+cVEp3BQOkqz+KIohw0PS79IA4pWI+OgtZc/o4=; b=lZO1UVa9hAhiIo60k9XvAj6q3cEcCiv1pWgH3I7tnjRBOsl8lcVreq25ZCegMs1LsM 3wHNwWApJHT0Ko2IzGjeaK/6XM+rSrHUH5UzcVKXXQqkoTHsghFW2Yejl2pGoiNLdXh9 TrJD9KDn/8zuDhW0bx8SzEV0VWaDshpM9aRWTlInhcCYMzuoSPS22wsQ8UI7aOjzbPMx xZuJshFkLOJqNJB7eEwTE/yYlbGtxz/5kEnEeygH4M5xOEv4DLwNTdhUW3MyGYITlS7h VdLN4AltaY/pGvkZKNn+9P3DaejcfcMl1lagkimNatWN//n0zRPwB3Th8LsbsZWVMaqt FPZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712078279; x=1712683079; 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=SlBVx+cVEp3BQOkqz+KIohw0PS79IA4pWI+OgtZc/o4=; b=dkF5mSCb0A2hoWjVWf9pqcbTB25PAkOHAOUyb/KkRtydm6Y2mhbF5zeeLspcZtlbJX mhYNOOEAHZYfpLbCnHHYuSuc8FarCB3788O7KiUypd+6OZrqaKvFrAQSA642pWi9EsZ2 sMyxdYJBobycX28uy72KgEaApuOXHnfnY/epuh2ssBmIXXLPkaMKmEyFP+ynaPY/M6Lq Ykc/LuC7yO7XqtuweCXlUISs6ghymbeTEVwXclTXOf41ixf5JaOQQ0NTipmHOVnV3Bjk zJkkIsBvMwhc/w+rEB+FhAJ3y9NmrdUMz1keKU8PaVfcUErvSwp4TokwzRGDEH/QePlr 876g== X-Gm-Message-State: AOJu0YxUDdVd1mCcLIoa48jrhHOAQi45gSO1rIfPyzj9ryyjkQ++Kk+d UZ/SBg8R6TMbfyqC90AdmvTvVjQ7kEemNvFy+VnQmwAhV8aXDc3+POKtAHfKz695vg3QKLrjz3l q X-Google-Smtp-Source: AGHT+IHLvNIChkFEfMW4NQeDCuUfRbZxelT7+/T6bzukYf8LuwmDnUptXLpbHQqo2WiUNJbo/U7SCQ== X-Received: by 2002:a17:902:e544:b0:1e0:b5d3:3f99 with SMTP id n4-20020a170902e54400b001e0b5d33f99mr211168plf.26.1712078279134; Tue, 02 Apr 2024 10:17:59 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id q15-20020a170902a3cf00b001e264b50964sm2219815plb.205.2024.04.02.10.17.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 10:17:58 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v5 7/8] net/tap: use libbpf to load new BPF program Date: Tue, 2 Apr 2024 10:12:39 -0700 Message-ID: <20240402171751.138324-8-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240402171751.138324-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240402171751.138324-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 alsow 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 | 14 +- drivers/net/tap/meson.build | 29 +-- drivers/net/tap/rte_eth_tap.c | 2 + drivers/net/tap/rte_eth_tap.h | 9 +- drivers/net/tap/tap_flow.c | 410 +++++++------------------------- drivers/net/tap/tap_flow.h | 16 +- drivers/net/tap/tap_rss.h | 10 +- drivers/net/tap/tap_tcmsgs.h | 4 +- 8 files changed, 127 insertions(+), 367 deletions(-) diff --git a/drivers/net/tap/bpf/meson.build b/drivers/net/tap/bpf/meson.build index f2c03a19fd..3f3c4e6602 100644 --- a/drivers/net/tap/bpf/meson.build +++ b/drivers/net/tap/bpf/meson.build @@ -3,15 +3,24 @@ enable_tap_rss = false +# Loading BPF requires libbpf libbpf = dependency('libbpf', 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 +51,7 @@ clang_flags = [ '-O2', '-Wall', '-Wextra', + max_queues, '-target', 'bpf', '-g', diff --git a/drivers/net/tap/meson.build b/drivers/net/tap/meson.build index 9cd124d53e..46ffd35beb 100644 --- a/drivers/net/tap/meson.build +++ b/drivers/net/tap/meson.build @@ -7,33 +7,22 @@ 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', ) -deps = ['bus_vdev', 'gso', 'hash'] +max_queues = '-DTAP_MAX_QUEUES=16' +cflags += max_queues -cflags += '-DTAP_MAX_QUEUES=8' +subdir('bpf') +if enable_tap_rss + cflags += '-DHAVE_BPF_RSS' + ext_deps += libbpf + sources += tap_rss_skel_h +endif -# input array for meson symbol search: -# [ "MACRO to define if found", "header for the search", -# "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 - config.set(arg[0], cc.has_header_symbol(arg[1], arg[2])) -endforeach -configure_file(output : 'tap_autoconf.h', configuration : config) +deps = ['bus_vdev', 'gso', 'hash'] require_iova_in_mbuf = false diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 38a1b2d825..b76c5bf527 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -1129,6 +1129,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); } for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) { @@ -1941,6 +1942,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; + pmd->rss = NULL; pmd->nlsk_fd = -1; pmd->gso_ctx_mp = NULL; diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h index dc8201020b..4e9ca6d826 100644 --- a/drivers/net/tap/rte_eth_tap.h +++ b/drivers/net/tap/rte_eth_tap.h @@ -79,12 +79,11 @@ struct pmd_internals { 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; + + struct tap_rss *rss; /* BPF program */ + uint16_t bpf_flowid; /* next BPF class id */ + 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 e154ea0ae0..77dc8e9741 100644 --- a/drivers/net/tap/tap_flow.c +++ b/drivers/net/tap/tap_flow.c @@ -15,26 +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 @@ -42,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; }; @@ -70,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; @@ -113,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, @@ -854,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, @@ -1105,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 = @@ -1136,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 *) @@ -1144,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; } @@ -1247,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); } @@ -1734,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. * @@ -1756,226 +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"); + int err; - return -ENOTSUP; + /* 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; } - /* - * 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 */ - - /* 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; - } - LIST_INSERT_HEAD(&pmd->rss_flows, rss_flow, next); - } - - 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, @@ -2008,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; @@ -2059,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 " @@ -2095,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..bc54af28ca 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,10 +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); @@ -57,10 +57,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 Tue Apr 2 17:12:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 139030 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 7D91C43DC3; Tue, 2 Apr 2024 19:19:06 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id BB70B40A73; Tue, 2 Apr 2024 19:18:06 +0200 (CEST) Received: from mail-pl1-f173.google.com (mail-pl1-f173.google.com [209.85.214.173]) by mails.dpdk.org (Postfix) with ESMTP id 6342F40685 for ; Tue, 2 Apr 2024 19:18:01 +0200 (CEST) Received: by mail-pl1-f173.google.com with SMTP id d9443c01a7336-1e0bfc42783so45377045ad.0 for ; Tue, 02 Apr 2024 10:18:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712078280; x=1712683080; 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=K0jbEH7ciiOiKWjlnbweaYkbKxNeRJujPSSyM1fxdOw=; b=chxihYDW0EGoCkaEP9m1mEw824aCIClJSU5Va+ZPBGC8PvWpFCOfIr2TLxVRUpxZKf 2B2O095PgrZsOygVWcL8EPA6rKDOPTeWJ7V9tPng7h4RcSyWPruh+TZFLQeBNTKV08Ia 3XVhQZTLiklqvwC+vfheqVv/4EGqiwerJDe0k4qwYTx1vVY3wyElUXKsHxI6KWdglOMg LCm30qVK6gSnFp3bD8iqaoHRhPYmcWhhbHSNsoblz+KE9eywPBwgPkUBqXWKuwWpWjIi sjRQOlePTBJb18IyTdNqGYHIOljVhSORuU/vPQqcGLYUPi0Wq7l/buSjCg5Nq/50G/WJ r4MA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712078280; x=1712683080; 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=K0jbEH7ciiOiKWjlnbweaYkbKxNeRJujPSSyM1fxdOw=; b=RkywqjGDprSHilZGxdoVEsuBdXBZknndIZGDTWybMFQfo2/SNYGCSHrdWOxjU8+zCQ +y6fylxKiSDeqxEREn5bj2uyOvUF+BUCa4QbPYOYu3UXHZoYWfxzVGjHwVccaVcPTqF6 vK0OyEkvortGFsqaycg6YpdOstYFsgo+puQnmebu5rXvYYzTjc3JdxEC1FJYPdE5PA0E j4aS6G++b0CJ6CzdvRmo9dvlzz9tpTi11u+O0hSKnO1NcWMMKFX67dh2eXgKlfpBzE2R wWMqDJ+senVjLHEvo6vIwZCdWvPV8K//E88rlwHu47XRhs4vOcIR7/35Yqf/52+DjzJW 7nSA== X-Gm-Message-State: AOJu0YxtTKcbnNbvEJtHcNB33FumFeNyOa5nl9Zhxkh6/PVtxeEMoeEP dJ8Qhr9Y3K3w/ohGn/PlRSsfVyKh5oK3caKrHgxVxW2MjZESAHUe0x2SELcIwVc5mjovIpLzL0r f X-Google-Smtp-Source: AGHT+IGS9H5Xj/rYQ9JphbibHXqCUPrD0wv/7x91j07QexkY4qYx7Ds5nws4kXYJ/m03lToOSAcOSw== X-Received: by 2002:a17:902:db06:b0:1e0:8800:8321 with SMTP id m6-20020a170902db0600b001e088008321mr17930485plx.11.1712078280107; Tue, 02 Apr 2024 10:18:00 -0700 (PDT) Received: from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id q15-20020a170902a3cf00b001e264b50964sm2219815plb.205.2024.04.02.10.17.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 10:17:59 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v5 8/8] net/tap: remove no longer used files Date: Tue, 2 Apr 2024 10:12:40 -0700 Message-ID: <20240402171751.138324-9-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240402171751.138324-1-stephen@networkplumber.org> References: <20240130034925.44869-1-stephen@networkplumber.org> <20240402171751.138324-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 | 1743 ------------------------------- 2 files changed, 1939 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 53fa76c4e6..0000000000 --- a/drivers/net/tap/tap_bpf_insns.h +++ /dev/null @@ -1,1743 +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. - */ - -#include - -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}, -};