All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements
@ 2023-10-30  5:12 Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 01/21] tap: Remove tap_probe_vnet_hdr_len() Akihiko Odaki
                   ` (20 more replies)
  0 siblings, 21 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

Based-on: <20230524064704.47711-1-akihiko.odaki@daynix.com>
("[PATCH 0/2] net: Update MemReentrancyGuard for NIC")

This series contains fixes and improvements for virtio-net RSS and hash
reporting feature.

V5 -> V6:
  Corrected the message for patch "virtio-net: Return an error when vhost
  cannot enable RSS".
  Removed changes to introduce asserts from "virtio-net: Return an error
  when vhost cannot enable RSS".
  Reorganized patches "virtio-net: Return an error when vhost cannot enable
  RSS" and "virtio-net: Do not clear VIRTIO_NET_F_RSS". This version now
  contains patches "virtio-net: Return an error when vhost cannot enable
  RSS" and "virtio-net: Enable software RSS".
  Rebased.

V4 -> V5:
  Added patch "virtio-net: Do not write hashes to peer buffer".

V3 -> V4:
  Extract patches "tap: Remove tap_receive()" and  "net: Remove flag
  propagation" from "net: Remove receive_raw()".
  Added patch "virtio-net: Always set populate_hash".
  Added patch "virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT".
  Added patch "ebpf: Use standard section name".
  Added patch "ebpf: Simplify error handling".
  Added patch "ebpf: Return 0 when configuration fails".
  Added patch "ebpf: Refactor tun_rss_steering_prog()".
  Added patch "ebpf: Add a separate target for skeleton".

V2 -> V3:
  Added patch "tap: Remove tap_probe_vnet_hdr_len()".
  Added patch "tap: Remove qemu_using_vnet_hdr()".
  Added patch "net: Move virtio-net header length assertion".
  Added patch "net: Remove receive_raw()".
  Added patch "tap: Shrink zeroed virtio-net header".
  Dropped patch "tap: Fix virtio-net header buffer size".

V1 -> V2:
  Added patch "ebpf: Fix RSS error handling".

Akihiko Odaki (21):
  tap: Remove tap_probe_vnet_hdr_len()
  tap: Remove qemu_using_vnet_hdr()
  net: Move virtio-net header length assertion
  net: Remove receive_raw()
  tap: Remove tap_receive()
  net: Remove flag propagation
  tap: Shrink zeroed virtio-net header
  virtio-net: Copy header only when necessary
  virtio-net: Disable RSS on reset
  virtio-net: Unify the logic to update NIC state for RSS
  virtio-net: Return an error when vhost cannot enable RSS
  virtio-net: Enable software RSS
  virtio-net: Always set populate_hash
  virtio-net: Do not write hashes to peer buffer
  virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT
  ebpf: Fix RSS error handling
  ebpf: Use standard section name
  ebpf: Simplify error handling
  ebpf: Return 0 when configuration fails
  ebpf: Refactor tun_rss_steering_prog()
  ebpf: Add a separate target for skeleton

 ebpf/rss.bpf.skeleton.h  | 1557 +++++++++++++++++++-------------------
 include/net/filter.h     |    3 -
 include/net/net.h        |    7 -
 include/net/queue.h      |    7 -
 include/sysemu/replay.h  |    2 +-
 net/tap_int.h            |    1 -
 ebpf/ebpf_rss.c          |   12 +-
 hw/net/e1000e.c          |    1 -
 hw/net/igb.c             |    1 -
 hw/net/net_tx_pkt.c      |    4 +-
 hw/net/virtio-net.c      |  310 ++++----
 hw/net/vmxnet3.c         |    2 -
 net/dump.c               |    8 +-
 net/filter-buffer.c      |    4 +-
 net/filter-mirror.c      |    6 +-
 net/filter-replay.c      |    3 +-
 net/filter-rewriter.c    |    5 +-
 net/filter.c             |    8 +-
 net/net.c                |   83 +-
 net/netmap.c             |    5 -
 net/queue.c              |   30 +-
 net/tap-bsd.c            |    5 -
 net/tap-linux.c          |   20 -
 net/tap-solaris.c        |    5 -
 net/tap-stub.c           |    5 -
 net/tap.c                |   74 +-
 replay/replay-net.c      |    8 +-
 tools/ebpf/rss.bpf.c     |   46 +-
 tools/ebpf/Makefile.ebpf |   15 +-
 29 files changed, 1016 insertions(+), 1221 deletions(-)

-- 
2.42.0



^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH v6 01/21] tap: Remove tap_probe_vnet_hdr_len()
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 02/21] tap: Remove qemu_using_vnet_hdr() Akihiko Odaki
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

It was necessary since an Linux older than 2.6.35 may implement the
virtio-net header but may not allow to change its length. Remove it
since such an old Linux is no longer supported.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 net/tap_int.h     |  1 -
 net/tap-bsd.c     |  5 -----
 net/tap-linux.c   | 20 --------------------
 net/tap-solaris.c |  5 -----
 net/tap-stub.c    |  5 -----
 net/tap.c         | 10 ++--------
 6 files changed, 2 insertions(+), 44 deletions(-)

diff --git a/net/tap_int.h b/net/tap_int.h
index 9a2175655b..8857ff299d 100644
--- a/net/tap_int.h
+++ b/net/tap_int.h
@@ -35,7 +35,6 @@ ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen);
 
 void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp);
 int tap_probe_vnet_hdr(int fd, Error **errp);
-int tap_probe_vnet_hdr_len(int fd, int len);
 int tap_probe_has_ufo(int fd);
 int tap_probe_has_uso(int fd);
 void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo,
diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index 274ea7bd2c..b4c84441ba 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -217,11 +217,6 @@ int tap_probe_has_uso(int fd)
     return 0;
 }
 
-int tap_probe_vnet_hdr_len(int fd, int len)
-{
-    return 0;
-}
-
 void tap_fd_set_vnet_hdr_len(int fd, int len)
 {
 }
diff --git a/net/tap-linux.c b/net/tap-linux.c
index c7e514ecb0..1226d5fda2 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -185,26 +185,6 @@ int tap_probe_has_uso(int fd)
     return 1;
 }
 
-/* Verify that we can assign given length */
-int tap_probe_vnet_hdr_len(int fd, int len)
-{
-    int orig;
-    if (ioctl(fd, TUNGETVNETHDRSZ, &orig) == -1) {
-        return 0;
-    }
-    if (ioctl(fd, TUNSETVNETHDRSZ, &len) == -1) {
-        return 0;
-    }
-    /* Restore original length: we can't handle failure. */
-    if (ioctl(fd, TUNSETVNETHDRSZ, &orig) == -1) {
-        fprintf(stderr, "TUNGETVNETHDRSZ ioctl() failed: %s. Exiting.\n",
-                strerror(errno));
-        abort();
-        return -errno;
-    }
-    return 1;
-}
-
 void tap_fd_set_vnet_hdr_len(int fd, int len)
 {
     if (ioctl(fd, TUNSETVNETHDRSZ, &len) == -1) {
diff --git a/net/tap-solaris.c b/net/tap-solaris.c
index 08b13af512..51b7830bef 100644
--- a/net/tap-solaris.c
+++ b/net/tap-solaris.c
@@ -221,11 +221,6 @@ int tap_probe_has_uso(int fd)
     return 0;
 }
 
-int tap_probe_vnet_hdr_len(int fd, int len)
-{
-    return 0;
-}
-
 void tap_fd_set_vnet_hdr_len(int fd, int len)
 {
 }
diff --git a/net/tap-stub.c b/net/tap-stub.c
index 4b24f61e3a..38673434cb 100644
--- a/net/tap-stub.c
+++ b/net/tap-stub.c
@@ -52,11 +52,6 @@ int tap_probe_has_uso(int fd)
     return 0;
 }
 
-int tap_probe_vnet_hdr_len(int fd, int len)
-{
-    return 0;
-}
-
 void tap_fd_set_vnet_hdr_len(int fd, int len)
 {
 }
diff --git a/net/tap.c b/net/tap.c
index c23d0323c2..5d6f292cfe 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -259,11 +259,7 @@ static bool tap_has_vnet_hdr(NetClientState *nc)
 
 static bool tap_has_vnet_hdr_len(NetClientState *nc, int len)
 {
-    TAPState *s = DO_UPCAST(TAPState, nc, nc);
-
-    assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
-
-    return !!tap_probe_vnet_hdr_len(s->fd, len);
+    return tap_has_vnet_hdr(nc);
 }
 
 static int tap_get_vnet_hdr_len(NetClientState *nc)
@@ -432,9 +428,7 @@ static TAPState *net_tap_fd_init(NetClientState *peer,
      * Make sure host header length is set correctly in tap:
      * it might have been modified by another instance of qemu.
      */
-    if (tap_probe_vnet_hdr_len(s->fd, s->host_vnet_hdr_len)) {
-        tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len);
-    }
+    tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len);
     tap_read_poll(s, true);
     s->vhost_net = NULL;
 
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 02/21] tap: Remove qemu_using_vnet_hdr()
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 01/21] tap: Remove tap_probe_vnet_hdr_len() Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 03/21] net: Move virtio-net header length assertion Akihiko Odaki
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki, Dmitry Fleytman,
	Sriram Yagnaraman, Luigi Rizzo, Giuseppe Lettieri,
	Vincenzo Maffione

Since qemu_set_vnet_hdr_len() is always called when
qemu_using_vnet_hdr() is called, we can merge them and save some code.

For consistency, express that the virtio-net header is not in use by
returning 0 with qemu_get_vnet_hdr_len() instead of having a dedicated
function, qemu_get_using_vnet_hdr().

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/net/net.h   |  6 ------
 hw/net/e1000e.c     |  1 -
 hw/net/igb.c        |  1 -
 hw/net/net_tx_pkt.c |  4 ++--
 hw/net/virtio-net.c |  3 ---
 hw/net/vmxnet3.c    |  2 --
 net/dump.c          |  4 +---
 net/net.c           | 18 ------------------
 net/netmap.c        |  5 -----
 net/tap.c           | 22 ++--------------------
 10 files changed, 5 insertions(+), 61 deletions(-)

diff --git a/include/net/net.h b/include/net/net.h
index ffbd2c8d56..d98a2b136a 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -57,8 +57,6 @@ typedef bool (HasUfo)(NetClientState *);
 typedef bool (HasUso)(NetClientState *);
 typedef bool (HasVnetHdr)(NetClientState *);
 typedef bool (HasVnetHdrLen)(NetClientState *, int);
-typedef bool (GetUsingVnetHdr)(NetClientState *);
-typedef void (UsingVnetHdr)(NetClientState *, bool);
 typedef void (SetOffload)(NetClientState *, int, int, int, int, int, int, int);
 typedef int (GetVnetHdrLen)(NetClientState *);
 typedef void (SetVnetHdrLen)(NetClientState *, int);
@@ -88,8 +86,6 @@ typedef struct NetClientInfo {
     HasUso *has_uso;
     HasVnetHdr *has_vnet_hdr;
     HasVnetHdrLen *has_vnet_hdr_len;
-    GetUsingVnetHdr *get_using_vnet_hdr;
-    UsingVnetHdr *using_vnet_hdr;
     SetOffload *set_offload;
     GetVnetHdrLen *get_vnet_hdr_len;
     SetVnetHdrLen *set_vnet_hdr_len;
@@ -194,8 +190,6 @@ bool qemu_has_ufo(NetClientState *nc);
 bool qemu_has_uso(NetClientState *nc);
 bool qemu_has_vnet_hdr(NetClientState *nc);
 bool qemu_has_vnet_hdr_len(NetClientState *nc, int len);
-bool qemu_get_using_vnet_hdr(NetClientState *nc);
-void qemu_using_vnet_hdr(NetClientState *nc, bool enable);
 void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
                       int ecn, int ufo, int uso4, int uso6);
 int qemu_get_vnet_hdr_len(NetClientState *nc);
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index e41a6c1038..4edb58858e 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -352,7 +352,6 @@ e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr)
     for (i = 0; i < s->conf.peers.queues; i++) {
         nc = qemu_get_subqueue(s->nic, i);
         qemu_set_vnet_hdr_len(nc->peer, sizeof(struct virtio_net_hdr));
-        qemu_using_vnet_hdr(nc->peer, true);
     }
 }
 
diff --git a/hw/net/igb.c b/hw/net/igb.c
index 8b713843d9..cfdb148051 100644
--- a/hw/net/igb.c
+++ b/hw/net/igb.c
@@ -339,7 +339,6 @@ igb_init_net_peer(IGBState *s, PCIDevice *pci_dev, uint8_t *macaddr)
     for (i = 0; i < s->conf.peers.queues; i++) {
         nc = qemu_get_subqueue(s->nic, i);
         qemu_set_vnet_hdr_len(nc->peer, sizeof(struct virtio_net_hdr));
-        qemu_using_vnet_hdr(nc->peer, true);
     }
 }
 
diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
index 2e5f58b3c9..668871f8d8 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/net_tx_pkt.c
@@ -578,7 +578,7 @@ static void net_tx_pkt_sendv(
 {
     NetClientState *nc = opaque;
 
-    if (qemu_get_using_vnet_hdr(nc->peer)) {
+    if (qemu_get_vnet_hdr_len(nc->peer)) {
         qemu_sendv_packet(nc, virt_iov, virt_iov_cnt);
     } else {
         qemu_sendv_packet(nc, iov, iov_cnt);
@@ -808,7 +808,7 @@ static bool net_tx_pkt_do_sw_fragmentation(struct NetTxPkt *pkt,
 
 bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState *nc)
 {
-    bool offload = qemu_get_using_vnet_hdr(nc->peer);
+    bool offload = !!qemu_get_vnet_hdr_len(nc->peer);
     return net_tx_pkt_send_custom(pkt, offload, net_tx_pkt_sendv, nc);
 }
 
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 80c56f0cfc..e12176acb1 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3728,9 +3728,6 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
 
     peer_test_vnet_hdr(n);
     if (peer_has_vnet_hdr(n)) {
-        for (i = 0; i < n->max_queue_pairs; i++) {
-            qemu_using_vnet_hdr(qemu_get_subqueue(n->nic, i)->peer, true);
-        }
         n->host_hdr_len = sizeof(struct virtio_net_hdr);
     } else {
         n->host_hdr_len = 0;
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 6fb4102d03..81ab8ada55 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2091,8 +2091,6 @@ static void vmxnet3_net_init(VMXNET3State *s)
     if (s->peer_has_vhdr) {
         qemu_set_vnet_hdr_len(qemu_get_queue(s->nic)->peer,
             sizeof(struct virtio_net_hdr));
-
-        qemu_using_vnet_hdr(qemu_get_queue(s->nic)->peer, 1);
     }
 
     qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
diff --git a/net/dump.c b/net/dump.c
index 16073f2458..956e34a123 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -154,10 +154,8 @@ static ssize_t filter_dump_receive_iov(NetFilterState *nf, NetClientState *sndr,
                                        int iovcnt, NetPacketSent *sent_cb)
 {
     NetFilterDumpState *nfds = FILTER_DUMP(nf);
-    int offset = qemu_get_using_vnet_hdr(nf->netdev) ?
-                 qemu_get_vnet_hdr_len(nf->netdev) : 0;
 
-    dump_receive_iov(&nfds->ds, iov, iovcnt, offset);
+    dump_receive_iov(&nfds->ds, iov, iovcnt, qemu_get_vnet_hdr_len(nf->netdev));
     return 0;
 }
 
diff --git a/net/net.c b/net/net.c
index cb88651db2..fda9a8f994 100644
--- a/net/net.c
+++ b/net/net.c
@@ -524,24 +524,6 @@ bool qemu_has_vnet_hdr_len(NetClientState *nc, int len)
     return nc->info->has_vnet_hdr_len(nc, len);
 }
 
-bool qemu_get_using_vnet_hdr(NetClientState *nc)
-{
-    if (!nc || !nc->info->get_using_vnet_hdr) {
-        return false;
-    }
-
-    return nc->info->get_using_vnet_hdr(nc);
-}
-
-void qemu_using_vnet_hdr(NetClientState *nc, bool enable)
-{
-    if (!nc || !nc->info->using_vnet_hdr) {
-        return;
-    }
-
-    nc->info->using_vnet_hdr(nc, enable);
-}
-
 void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
                           int ecn, int ufo, int uso4, int uso6)
 {
diff --git a/net/netmap.c b/net/netmap.c
index 241b27c8e9..297510e190 100644
--- a/net/netmap.c
+++ b/net/netmap.c
@@ -351,10 +351,6 @@ static bool netmap_has_vnet_hdr(NetClientState *nc)
     return netmap_has_vnet_hdr_len(nc, sizeof(struct virtio_net_hdr));
 }
 
-static void netmap_using_vnet_hdr(NetClientState *nc, bool enable)
-{
-}
-
 static void netmap_set_vnet_hdr_len(NetClientState *nc, int len)
 {
     NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
@@ -393,7 +389,6 @@ static NetClientInfo net_netmap_info = {
     .has_ufo = netmap_has_vnet_hdr,
     .has_vnet_hdr = netmap_has_vnet_hdr,
     .has_vnet_hdr_len = netmap_has_vnet_hdr_len,
-    .using_vnet_hdr = netmap_using_vnet_hdr,
     .set_offload = netmap_set_offload,
     .set_vnet_hdr_len = netmap_set_vnet_hdr_len,
 };
diff --git a/net/tap.c b/net/tap.c
index 5d6f292cfe..0e031ee9fa 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -266,7 +266,7 @@ static int tap_get_vnet_hdr_len(NetClientState *nc)
 {
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
 
-    return s->host_vnet_hdr_len;
+    return s->using_vnet_hdr ? s->host_vnet_hdr_len : 0;
 }
 
 static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
@@ -280,23 +280,7 @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
 
     tap_fd_set_vnet_hdr_len(s->fd, len);
     s->host_vnet_hdr_len = len;
-}
-
-static bool tap_get_using_vnet_hdr(NetClientState *nc)
-{
-    TAPState *s = DO_UPCAST(TAPState, nc, nc);
-
-    return s->using_vnet_hdr;
-}
-
-static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
-{
-    TAPState *s = DO_UPCAST(TAPState, nc, nc);
-
-    assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
-    assert(!!s->host_vnet_hdr_len == using_vnet_hdr);
-
-    s->using_vnet_hdr = using_vnet_hdr;
+    s->using_vnet_hdr = true;
 }
 
 static int tap_set_vnet_le(NetClientState *nc, bool is_le)
@@ -394,8 +378,6 @@ static NetClientInfo net_tap_info = {
     .has_uso = tap_has_uso,
     .has_vnet_hdr = tap_has_vnet_hdr,
     .has_vnet_hdr_len = tap_has_vnet_hdr_len,
-    .get_using_vnet_hdr = tap_get_using_vnet_hdr,
-    .using_vnet_hdr = tap_using_vnet_hdr,
     .set_offload = tap_set_offload,
     .get_vnet_hdr_len = tap_get_vnet_hdr_len,
     .set_vnet_hdr_len = tap_set_vnet_hdr_len,
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 03/21] net: Move virtio-net header length assertion
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 01/21] tap: Remove tap_probe_vnet_hdr_len() Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 02/21] tap: Remove qemu_using_vnet_hdr() Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 04/21] net: Remove receive_raw() Akihiko Odaki
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

The virtio-net header length assertion should happen for any clients.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 net/net.c | 5 +++++
 net/tap.c | 3 ---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/net/net.c b/net/net.c
index fda9a8f994..717d48ce15 100644
--- a/net/net.c
+++ b/net/net.c
@@ -56,6 +56,7 @@
 #include "net/filter.h"
 #include "qapi/string-output-visitor.h"
 #include "qapi/qobject-input-visitor.h"
+#include "standard-headers/linux/virtio_net.h"
 
 /* Net bridge is currently not supported for W32. */
 #if !defined(_WIN32)
@@ -549,6 +550,10 @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
         return;
     }
 
+    assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) ||
+           len == sizeof(struct virtio_net_hdr) ||
+           len == sizeof(struct virtio_net_hdr_v1_hash));
+
     nc->vnet_hdr_len = len;
     nc->info->set_vnet_hdr_len(nc, len);
 }
diff --git a/net/tap.c b/net/tap.c
index 0e031ee9fa..d94731b2fa 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -274,9 +274,6 @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
 
     assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
-    assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) ||
-           len == sizeof(struct virtio_net_hdr) ||
-           len == sizeof(struct virtio_net_hdr_v1_hash));
 
     tap_fd_set_vnet_hdr_len(s->fd, len);
     s->host_vnet_hdr_len = len;
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 04/21] net: Remove receive_raw()
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (2 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 03/21] net: Move virtio-net header length assertion Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 05/21] tap: Remove tap_receive() Akihiko Odaki
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

While netmap implements virtio-net header, it does not implement
receive_raw(). Instead of implementing receive_raw for netmap, add
virtio-net headers in the common code and use receive_iov()/receive()
instead. This also fixes the buffer size for the virtio-net header.

Fixes: fbbdbddec0 ("tap: allow extended virtio header with hash info")
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/net/net.h   |  1 -
 include/net/queue.h |  1 -
 net/net.c           | 17 +++++++++--------
 net/queue.c         | 30 ++++++++++--------------------
 net/tap.c           |  1 -
 5 files changed, 19 insertions(+), 31 deletions(-)

diff --git a/include/net/net.h b/include/net/net.h
index d98a2b136a..5bc1f82550 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -72,7 +72,6 @@ typedef struct NetClientInfo {
     NetClientDriver type;
     size_t size;
     NetReceive *receive;
-    NetReceive *receive_raw;
     NetReceiveIOV *receive_iov;
     NetCanReceive *can_receive;
     NetStart *start;
diff --git a/include/net/queue.h b/include/net/queue.h
index 9f2f289d77..7a43863be2 100644
--- a/include/net/queue.h
+++ b/include/net/queue.h
@@ -31,7 +31,6 @@ typedef struct NetQueue NetQueue;
 typedef void (NetPacketSent) (NetClientState *sender, ssize_t ret);
 
 #define QEMU_NET_PACKET_FLAG_NONE  0
-#define QEMU_NET_PACKET_FLAG_RAW  (1<<0)
 
 /* Returns:
  *   >0 - success
diff --git a/net/net.c b/net/net.c
index 717d48ce15..ad8ecce5d6 100644
--- a/net/net.c
+++ b/net/net.c
@@ -761,8 +761,13 @@ ssize_t qemu_receive_packet_iov(NetClientState *nc, const struct iovec *iov,
 
 ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
 {
-    return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
-                                             buf, size, NULL);
+    struct virtio_net_hdr_v1_hash vnet_hdr = { };
+    struct iovec iov[] = {
+        { .iov_base = &vnet_hdr, .iov_len = nc->vnet_hdr_len },
+        { .iov_base = (void *)buf, .iov_len = size }
+    };
+
+    return qemu_sendv_packet_async(nc, iov, ARRAY_SIZE(iov), NULL);
 }
 
 static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
@@ -786,11 +791,7 @@ static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
         offset = iov_to_buf(iov, iovcnt, 0, buf, offset);
     }
 
-    if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
-        ret = nc->info->receive_raw(nc, buffer, offset);
-    } else {
-        ret = nc->info->receive(nc, buffer, offset);
-    }
+    ret = nc->info->receive(nc, buffer, offset);
 
     g_free(buf);
     return ret;
@@ -823,7 +824,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
         owned_reentrancy_guard->engaged_in_io = true;
     }
 
-    if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) {
+    if (nc->info->receive_iov) {
         ret = nc->info->receive_iov(nc, iov, iovcnt);
     } else {
         ret = nc_sendv_compat(nc, iov, iovcnt, flags);
diff --git a/net/queue.c b/net/queue.c
index c872d51df8..70d29d7ac0 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -43,7 +43,6 @@
 struct NetPacket {
     QTAILQ_ENTRY(NetPacket) entry;
     NetClientState *sender;
-    unsigned flags;
     int size;
     NetPacketSent *sent_cb;
     uint8_t data[];
@@ -92,7 +91,6 @@ void qemu_del_net_queue(NetQueue *queue)
 
 static void qemu_net_queue_append(NetQueue *queue,
                                   NetClientState *sender,
-                                  unsigned flags,
                                   const uint8_t *buf,
                                   size_t size,
                                   NetPacketSent *sent_cb)
@@ -104,7 +102,6 @@ static void qemu_net_queue_append(NetQueue *queue,
     }
     packet = g_malloc(sizeof(NetPacket) + size);
     packet->sender = sender;
-    packet->flags = flags;
     packet->size = size;
     packet->sent_cb = sent_cb;
     memcpy(packet->data, buf, size);
@@ -115,7 +112,6 @@ static void qemu_net_queue_append(NetQueue *queue,
 
 void qemu_net_queue_append_iov(NetQueue *queue,
                                NetClientState *sender,
-                               unsigned flags,
                                const struct iovec *iov,
                                int iovcnt,
                                NetPacketSent *sent_cb)
@@ -134,7 +130,6 @@ void qemu_net_queue_append_iov(NetQueue *queue,
     packet = g_malloc(sizeof(NetPacket) + max_len);
     packet->sender = sender;
     packet->sent_cb = sent_cb;
-    packet->flags = flags;
     packet->size = 0;
 
     for (i = 0; i < iovcnt; i++) {
@@ -150,7 +145,6 @@ void qemu_net_queue_append_iov(NetQueue *queue,
 
 static ssize_t qemu_net_queue_deliver(NetQueue *queue,
                                       NetClientState *sender,
-                                      unsigned flags,
                                       const uint8_t *data,
                                       size_t size)
 {
@@ -161,7 +155,7 @@ static ssize_t qemu_net_queue_deliver(NetQueue *queue,
     };
 
     queue->delivering = 1;
-    ret = queue->deliver(sender, flags, &iov, 1, queue->opaque);
+    ret = queue->deliver(sender, &iov, 1, queue->opaque);
     queue->delivering = 0;
 
     return ret;
@@ -169,14 +163,13 @@ static ssize_t qemu_net_queue_deliver(NetQueue *queue,
 
 static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue,
                                           NetClientState *sender,
-                                          unsigned flags,
                                           const struct iovec *iov,
                                           int iovcnt)
 {
     ssize_t ret = -1;
 
     queue->delivering = 1;
-    ret = queue->deliver(sender, flags, iov, iovcnt, queue->opaque);
+    ret = queue->deliver(sender, iov, iovcnt, queue->opaque);
     queue->delivering = 0;
 
     return ret;
@@ -190,7 +183,7 @@ ssize_t qemu_net_queue_receive(NetQueue *queue,
         return 0;
     }
 
-    return qemu_net_queue_deliver(queue, NULL, 0, data, size);
+    return qemu_net_queue_deliver(queue, NULL, data, size);
 }
 
 ssize_t qemu_net_queue_receive_iov(NetQueue *queue,
@@ -201,12 +194,11 @@ ssize_t qemu_net_queue_receive_iov(NetQueue *queue,
         return 0;
     }
 
-    return qemu_net_queue_deliver_iov(queue, NULL, 0, iov, iovcnt);
+    return qemu_net_queue_deliver_iov(queue, NULL, iov, iovcnt);
 }
 
 ssize_t qemu_net_queue_send(NetQueue *queue,
                             NetClientState *sender,
-                            unsigned flags,
                             const uint8_t *data,
                             size_t size,
                             NetPacketSent *sent_cb)
@@ -214,13 +206,13 @@ ssize_t qemu_net_queue_send(NetQueue *queue,
     ssize_t ret;
 
     if (queue->delivering || !qemu_can_send_packet(sender)) {
-        qemu_net_queue_append(queue, sender, flags, data, size, sent_cb);
+        qemu_net_queue_append(queue, sender, data, size, sent_cb);
         return 0;
     }
 
-    ret = qemu_net_queue_deliver(queue, sender, flags, data, size);
+    ret = qemu_net_queue_deliver(queue, sender, data, size);
     if (ret == 0) {
-        qemu_net_queue_append(queue, sender, flags, data, size, sent_cb);
+        qemu_net_queue_append(queue, sender, data, size, sent_cb);
         return 0;
     }
 
@@ -231,7 +223,6 @@ ssize_t qemu_net_queue_send(NetQueue *queue,
 
 ssize_t qemu_net_queue_send_iov(NetQueue *queue,
                                 NetClientState *sender,
-                                unsigned flags,
                                 const struct iovec *iov,
                                 int iovcnt,
                                 NetPacketSent *sent_cb)
@@ -239,13 +230,13 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue,
     ssize_t ret;
 
     if (queue->delivering || !qemu_can_send_packet(sender)) {
-        qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, sent_cb);
+        qemu_net_queue_append_iov(queue, sender, iov, iovcnt, sent_cb);
         return 0;
     }
 
-    ret = qemu_net_queue_deliver_iov(queue, sender, flags, iov, iovcnt);
+    ret = qemu_net_queue_deliver_iov(queue, sender, iov, iovcnt);
     if (ret == 0) {
-        qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, sent_cb);
+        qemu_net_queue_append_iov(queue, sender, iov, iovcnt, sent_cb);
         return 0;
     }
 
@@ -285,7 +276,6 @@ bool qemu_net_queue_flush(NetQueue *queue)
 
         ret = qemu_net_queue_deliver(queue,
                                      packet->sender,
-                                     packet->flags,
                                      packet->data,
                                      packet->size);
         if (ret == 0) {
diff --git a/net/tap.c b/net/tap.c
index d94731b2fa..d54e90f184 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -367,7 +367,6 @@ static NetClientInfo net_tap_info = {
     .type = NET_CLIENT_DRIVER_TAP,
     .size = sizeof(TAPState),
     .receive = tap_receive,
-    .receive_raw = tap_receive_raw,
     .receive_iov = tap_receive_iov,
     .poll = tap_poll,
     .cleanup = tap_cleanup,
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 05/21] tap: Remove tap_receive()
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (3 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 04/21] net: Remove receive_raw() Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30 18:52   ` Zhang, Chen
  2023-10-30  5:12 ` [PATCH v6 06/21] net: Remove flag propagation Akihiko Odaki
                   ` (15 subsequent siblings)
  20 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

The receive member of NetClientInfo is only for legacy clients and the
receive_iov member is always used when it is set.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 net/tap.c | 36 ------------------------------------
 1 file changed, 36 deletions(-)

diff --git a/net/tap.c b/net/tap.c
index d54e90f184..ab4e5a0e91 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -133,41 +133,6 @@ static ssize_t tap_receive_iov(NetClientState *nc, const struct iovec *iov,
     return tap_write_packet(s, iovp, iovcnt);
 }
 
-static ssize_t tap_receive_raw(NetClientState *nc, const uint8_t *buf, size_t size)
-{
-    TAPState *s = DO_UPCAST(TAPState, nc, nc);
-    struct iovec iov[2];
-    int iovcnt = 0;
-    struct virtio_net_hdr_mrg_rxbuf hdr = { };
-
-    if (s->host_vnet_hdr_len) {
-        iov[iovcnt].iov_base = &hdr;
-        iov[iovcnt].iov_len  = s->host_vnet_hdr_len;
-        iovcnt++;
-    }
-
-    iov[iovcnt].iov_base = (char *)buf;
-    iov[iovcnt].iov_len  = size;
-    iovcnt++;
-
-    return tap_write_packet(s, iov, iovcnt);
-}
-
-static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size)
-{
-    TAPState *s = DO_UPCAST(TAPState, nc, nc);
-    struct iovec iov[1];
-
-    if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
-        return tap_receive_raw(nc, buf, size);
-    }
-
-    iov[0].iov_base = (char *)buf;
-    iov[0].iov_len  = size;
-
-    return tap_write_packet(s, iov, 1);
-}
-
 #ifndef __sun__
 ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)
 {
@@ -366,7 +331,6 @@ int tap_get_fd(NetClientState *nc)
 static NetClientInfo net_tap_info = {
     .type = NET_CLIENT_DRIVER_TAP,
     .size = sizeof(TAPState),
-    .receive = tap_receive,
     .receive_iov = tap_receive_iov,
     .poll = tap_poll,
     .cleanup = tap_cleanup,
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 06/21] net: Remove flag propagation
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (4 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 05/21] tap: Remove tap_receive() Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-11-10  7:35   ` Pavel Dovgalyuk
  2023-10-30  5:12 ` [PATCH v6 07/21] tap: Shrink zeroed virtio-net header Akihiko Odaki
                   ` (14 subsequent siblings)
  20 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki, Pavel Dovgalyuk,
	Paolo Bonzini, Zhang Chen, Li Zhijian

There is no defined flag now.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/net/filter.h    |  3 ---
 include/net/queue.h     |  6 ------
 include/sysemu/replay.h |  2 +-
 net/dump.c              |  4 ++--
 net/filter-buffer.c     |  4 +---
 net/filter-mirror.c     |  6 ++----
 net/filter-replay.c     |  3 +--
 net/filter-rewriter.c   |  5 ++---
 net/filter.c            |  8 +++-----
 net/net.c               | 43 ++++++++++++++---------------------------
 replay/replay-net.c     |  8 ++------
 11 files changed, 28 insertions(+), 64 deletions(-)

diff --git a/include/net/filter.h b/include/net/filter.h
index 27ffc630df..e523771e72 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -26,7 +26,6 @@ typedef void (FilterCleanup) (NetFilterState *nf);
  */
 typedef ssize_t (FilterReceiveIOV)(NetFilterState *nc,
                                    NetClientState *sender,
-                                   unsigned flags,
                                    const struct iovec *iov,
                                    int iovcnt,
                                    NetPacketSent *sent_cb);
@@ -65,14 +64,12 @@ struct NetFilterState {
 ssize_t qemu_netfilter_receive(NetFilterState *nf,
                                NetFilterDirection direction,
                                NetClientState *sender,
-                               unsigned flags,
                                const struct iovec *iov,
                                int iovcnt,
                                NetPacketSent *sent_cb);
 
 /* pass the packet to the next filter */
 ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
-                                    unsigned flags,
                                     const struct iovec *iov,
                                     int iovcnt,
                                     void *opaque);
diff --git a/include/net/queue.h b/include/net/queue.h
index 7a43863be2..571f4e1436 100644
--- a/include/net/queue.h
+++ b/include/net/queue.h
@@ -30,15 +30,12 @@ typedef struct NetQueue NetQueue;
 
 typedef void (NetPacketSent) (NetClientState *sender, ssize_t ret);
 
-#define QEMU_NET_PACKET_FLAG_NONE  0
-
 /* Returns:
  *   >0 - success
  *    0 - queue packet for future redelivery
  *   <0 - failure (discard packet)
  */
 typedef ssize_t (NetQueueDeliverFunc)(NetClientState *sender,
-                                      unsigned flags,
                                       const struct iovec *iov,
                                       int iovcnt,
                                       void *opaque);
@@ -47,7 +44,6 @@ NetQueue *qemu_new_net_queue(NetQueueDeliverFunc *deliver, void *opaque);
 
 void qemu_net_queue_append_iov(NetQueue *queue,
                                NetClientState *sender,
-                               unsigned flags,
                                const struct iovec *iov,
                                int iovcnt,
                                NetPacketSent *sent_cb);
@@ -64,14 +60,12 @@ ssize_t qemu_net_queue_receive_iov(NetQueue *queue,
 
 ssize_t qemu_net_queue_send(NetQueue *queue,
                             NetClientState *sender,
-                            unsigned flags,
                             const uint8_t *data,
                             size_t size,
                             NetPacketSent *sent_cb);
 
 ssize_t qemu_net_queue_send_iov(NetQueue *queue,
                                 NetClientState *sender,
-                                unsigned flags,
                                 const struct iovec *iov,
                                 int iovcnt,
                                 NetPacketSent *sent_cb);
diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
index 08aae5869f..67b2d3ac73 100644
--- a/include/sysemu/replay.h
+++ b/include/sysemu/replay.h
@@ -158,7 +158,7 @@ ReplayNetState *replay_register_net(NetFilterState *nfs);
 /*! Unregisters replay network filter. */
 void replay_unregister_net(ReplayNetState *rns);
 /*! Called to write network packet to the replay log. */
-void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
+void replay_net_packet_event(ReplayNetState *rns,
                              const struct iovec *iov, int iovcnt);
 
 /* Audio */
diff --git a/net/dump.c b/net/dump.c
index 956e34a123..dd8ada9b5e 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -150,8 +150,8 @@ struct NetFilterDumpState {
 };
 
 static ssize_t filter_dump_receive_iov(NetFilterState *nf, NetClientState *sndr,
-                                       unsigned flags, const struct iovec *iov,
-                                       int iovcnt, NetPacketSent *sent_cb)
+                                       const struct iovec *iov, int iovcnt,
+                                       NetPacketSent *sent_cb)
 {
     NetFilterDumpState *nfds = FILTER_DUMP(nf);
 
diff --git a/net/filter-buffer.c b/net/filter-buffer.c
index 283dc9cbe6..6d8b581cd8 100644
--- a/net/filter-buffer.c
+++ b/net/filter-buffer.c
@@ -58,7 +58,6 @@ static void filter_buffer_release_timer(void *opaque)
 /* filter APIs */
 static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
                                          NetClientState *sender,
-                                         unsigned flags,
                                          const struct iovec *iov,
                                          int iovcnt,
                                          NetPacketSent *sent_cb)
@@ -79,8 +78,7 @@ static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
      * the packets without caring about the receiver. This is suboptimal.
      * May need more thoughts (e.g keeping sent_cb).
      */
-    qemu_net_queue_append_iov(s->incoming_queue, sender, flags,
-                              iov, iovcnt, NULL);
+    qemu_net_queue_append_iov(s->incoming_queue, sender, iov, iovcnt, NULL);
     return iov_size(iov, iovcnt);
 }
 
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index 34a63b5dbb..752571a548 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -145,12 +145,12 @@ static void redirector_to_filter(NetFilterState *nf,
 
     if (nf->direction == NET_FILTER_DIRECTION_ALL ||
         nf->direction == NET_FILTER_DIRECTION_TX) {
-        qemu_netfilter_pass_to_next(nf->netdev, 0, &iov, 1, nf);
+        qemu_netfilter_pass_to_next(nf->netdev, &iov, 1, nf);
     }
 
     if (nf->direction == NET_FILTER_DIRECTION_ALL ||
         nf->direction == NET_FILTER_DIRECTION_RX) {
-        qemu_netfilter_pass_to_next(nf->netdev->peer, 0, &iov, 1, nf);
+        qemu_netfilter_pass_to_next(nf->netdev->peer, &iov, 1, nf);
      }
 }
 
@@ -190,7 +190,6 @@ static void redirector_chr_event(void *opaque, QEMUChrEvent event)
 
 static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
                                          NetClientState *sender,
-                                         unsigned flags,
                                          const struct iovec *iov,
                                          int iovcnt,
                                          NetPacketSent *sent_cb)
@@ -212,7 +211,6 @@ static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
 
 static ssize_t filter_redirector_receive_iov(NetFilterState *nf,
                                              NetClientState *sender,
-                                             unsigned flags,
                                              const struct iovec *iov,
                                              int iovcnt,
                                              NetPacketSent *sent_cb)
diff --git a/net/filter-replay.c b/net/filter-replay.c
index 54690676ef..ab132f6f24 100644
--- a/net/filter-replay.c
+++ b/net/filter-replay.c
@@ -31,7 +31,6 @@ struct NetFilterReplayState {
 
 static ssize_t filter_replay_receive_iov(NetFilterState *nf,
                                          NetClientState *sndr,
-                                         unsigned flags,
                                          const struct iovec *iov,
                                          int iovcnt, NetPacketSent *sent_cb)
 {
@@ -39,7 +38,7 @@ static ssize_t filter_replay_receive_iov(NetFilterState *nf,
     switch (replay_mode) {
     case REPLAY_MODE_RECORD:
         if (nf->netdev == sndr) {
-            replay_net_packet_event(nfrs->rns, flags, iov, iovcnt);
+            replay_net_packet_event(nfrs->rns, iov, iovcnt);
             return iov_size(iov, iovcnt);
         }
         return 0;
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
index c18c4c2019..5da0b097db 100644
--- a/net/filter-rewriter.c
+++ b/net/filter-rewriter.c
@@ -251,7 +251,6 @@ static int handle_secondary_tcp_pkt(RewriterState *rf,
 
 static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
                                          NetClientState *sender,
-                                         unsigned flags,
                                          const struct iovec *iov,
                                          int iovcnt,
                                          NetPacketSent *sent_cb)
@@ -294,7 +293,7 @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
         if (sender == nf->netdev) {
             /* NET_FILTER_DIRECTION_TX */
             if (!handle_primary_tcp_pkt(s, conn, pkt, &key)) {
-                qemu_net_queue_send(s->incoming_queue, sender, 0,
+                qemu_net_queue_send(s->incoming_queue, sender,
                 (const uint8_t *)pkt->data, pkt->size, NULL);
                 packet_destroy(pkt, NULL);
                 pkt = NULL;
@@ -307,7 +306,7 @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
         } else {
             /* NET_FILTER_DIRECTION_RX */
             if (!handle_secondary_tcp_pkt(s, conn, pkt, &key)) {
-                qemu_net_queue_send(s->incoming_queue, sender, 0,
+                qemu_net_queue_send(s->incoming_queue, sender,
                 (const uint8_t *)pkt->data, pkt->size, NULL);
                 packet_destroy(pkt, NULL);
                 pkt = NULL;
diff --git a/net/filter.c b/net/filter.c
index 3335908771..cc870114b7 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -28,7 +28,6 @@ static inline bool qemu_can_skip_netfilter(NetFilterState *nf)
 ssize_t qemu_netfilter_receive(NetFilterState *nf,
                                NetFilterDirection direction,
                                NetClientState *sender,
-                               unsigned flags,
                                const struct iovec *iov,
                                int iovcnt,
                                NetPacketSent *sent_cb)
@@ -39,7 +38,7 @@ ssize_t qemu_netfilter_receive(NetFilterState *nf,
     if (nf->direction == direction ||
         nf->direction == NET_FILTER_DIRECTION_ALL) {
         return NETFILTER_GET_CLASS(OBJECT(nf))->receive_iov(
-                                   nf, sender, flags, iov, iovcnt, sent_cb);
+                                   nf, sender, iov, iovcnt, sent_cb);
     }
 
     return 0;
@@ -62,7 +61,6 @@ static NetFilterState *netfilter_next(NetFilterState *nf,
 }
 
 ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
-                                    unsigned flags,
                                     const struct iovec *iov,
                                     int iovcnt,
                                     void *opaque)
@@ -96,7 +94,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
          * to the sender, so sent_cb shouldn't be called later, just
          * pass NULL to next.
          */
-        ret = qemu_netfilter_receive(next, direction, sender, flags, iov,
+        ret = qemu_netfilter_receive(next, direction, sender, iov,
                                      iovcnt, NULL);
         if (ret) {
             return ret;
@@ -111,7 +109,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
      */
     if (sender && sender->peer) {
         qemu_net_queue_send_iov(sender->peer->incoming_queue,
-                                sender, flags, iov, iovcnt, NULL);
+                                sender, iov, iovcnt, NULL);
     }
 
 out:
diff --git a/net/net.c b/net/net.c
index ad8ecce5d6..9883f12940 100644
--- a/net/net.c
+++ b/net/net.c
@@ -250,7 +250,6 @@ static void qemu_net_client_destructor(NetClientState *nc)
     g_free(nc);
 }
 static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
-                                       unsigned flags,
                                        const struct iovec *iov,
                                        int iovcnt,
                                        void *opaque);
@@ -613,7 +612,6 @@ int qemu_can_send_packet(NetClientState *sender)
 static ssize_t filter_receive_iov(NetClientState *nc,
                                   NetFilterDirection direction,
                                   NetClientState *sender,
-                                  unsigned flags,
                                   const struct iovec *iov,
                                   int iovcnt,
                                   NetPacketSent *sent_cb)
@@ -623,7 +621,7 @@ static ssize_t filter_receive_iov(NetClientState *nc,
 
     if (direction == NET_FILTER_DIRECTION_TX) {
         QTAILQ_FOREACH(nf, &nc->filters, next) {
-            ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
+            ret = qemu_netfilter_receive(nf, direction, sender, iov,
                                          iovcnt, sent_cb);
             if (ret) {
                 return ret;
@@ -631,7 +629,7 @@ static ssize_t filter_receive_iov(NetClientState *nc,
         }
     } else {
         QTAILQ_FOREACH_REVERSE(nf, &nc->filters, next) {
-            ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
+            ret = qemu_netfilter_receive(nf, direction, sender, iov,
                                          iovcnt, sent_cb);
             if (ret) {
                 return ret;
@@ -645,7 +643,6 @@ static ssize_t filter_receive_iov(NetClientState *nc,
 static ssize_t filter_receive(NetClientState *nc,
                               NetFilterDirection direction,
                               NetClientState *sender,
-                              unsigned flags,
                               const uint8_t *data,
                               size_t size,
                               NetPacketSent *sent_cb)
@@ -655,7 +652,7 @@ static ssize_t filter_receive(NetClientState *nc,
         .iov_len = size
     };
 
-    return filter_receive_iov(nc, direction, sender, flags, &iov, 1, sent_cb);
+    return filter_receive_iov(nc, direction, sender, &iov, 1, sent_cb);
 }
 
 void qemu_purge_queued_packets(NetClientState *nc)
@@ -692,10 +689,9 @@ void qemu_flush_queued_packets(NetClientState *nc)
     qemu_flush_or_purge_queued_packets(nc, false);
 }
 
-static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
-                                                 unsigned flags,
-                                                 const uint8_t *buf, int size,
-                                                 NetPacketSent *sent_cb)
+ssize_t qemu_send_packet_async(NetClientState *sender,
+                               const uint8_t *buf, int size,
+                               NetPacketSent *sent_cb)
 {
     NetQueue *queue;
     int ret;
@@ -711,28 +707,20 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
 
     /* Let filters handle the packet first */
     ret = filter_receive(sender, NET_FILTER_DIRECTION_TX,
-                         sender, flags, buf, size, sent_cb);
+                         sender, buf, size, sent_cb);
     if (ret) {
         return ret;
     }
 
     ret = filter_receive(sender->peer, NET_FILTER_DIRECTION_RX,
-                         sender, flags, buf, size, sent_cb);
+                         sender, buf, size, sent_cb);
     if (ret) {
         return ret;
     }
 
     queue = sender->peer->incoming_queue;
 
-    return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
-}
-
-ssize_t qemu_send_packet_async(NetClientState *sender,
-                               const uint8_t *buf, int size,
-                               NetPacketSent *sent_cb)
-{
-    return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE,
-                                             buf, size, sent_cb);
+    return qemu_net_queue_send(queue, sender, buf, size, sent_cb);
 }
 
 ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
@@ -771,7 +759,7 @@ ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
 }
 
 static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
-                               int iovcnt, unsigned flags)
+                               int iovcnt)
 {
     uint8_t *buf = NULL;
     uint8_t *buffer;
@@ -798,7 +786,6 @@ static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
 }
 
 static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
-                                       unsigned flags,
                                        const struct iovec *iov,
                                        int iovcnt,
                                        void *opaque)
@@ -827,7 +814,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
     if (nc->info->receive_iov) {
         ret = nc->info->receive_iov(nc, iov, iovcnt);
     } else {
-        ret = nc_sendv_compat(nc, iov, iovcnt, flags);
+        ret = nc_sendv_compat(nc, iov, iovcnt);
     }
 
     if (owned_reentrancy_guard) {
@@ -859,22 +846,20 @@ ssize_t qemu_sendv_packet_async(NetClientState *sender,
 
     /* Let filters handle the packet first */
     ret = filter_receive_iov(sender, NET_FILTER_DIRECTION_TX, sender,
-                             QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
+                             iov, iovcnt, sent_cb);
     if (ret) {
         return ret;
     }
 
     ret = filter_receive_iov(sender->peer, NET_FILTER_DIRECTION_RX, sender,
-                             QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
+                             iov, iovcnt, sent_cb);
     if (ret) {
         return ret;
     }
 
     queue = sender->peer->incoming_queue;
 
-    return qemu_net_queue_send_iov(queue, sender,
-                                   QEMU_NET_PACKET_FLAG_NONE,
-                                   iov, iovcnt, sent_cb);
+    return qemu_net_queue_send_iov(queue, sender, iov, iovcnt, sent_cb);
 }
 
 ssize_t
diff --git a/replay/replay-net.c b/replay/replay-net.c
index 3b70f71cf1..87e6d68f4e 100644
--- a/replay/replay-net.c
+++ b/replay/replay-net.c
@@ -24,7 +24,6 @@ struct ReplayNetState {
 
 typedef struct NetEvent {
     uint8_t id;
-    uint32_t flags;
     uint8_t *data;
     size_t size;
 } NetEvent;
@@ -50,11 +49,10 @@ void replay_unregister_net(ReplayNetState *rns)
     g_free(rns);
 }
 
-void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
+void replay_net_packet_event(ReplayNetState *rns,
                              const struct iovec *iov, int iovcnt)
 {
     NetEvent *event = g_new(NetEvent, 1);
-    event->flags = flags;
     event->data = g_malloc(iov_size(iov, iovcnt));
     event->size = iov_size(iov, iovcnt);
     event->id = rns->id;
@@ -74,7 +72,7 @@ void replay_event_net_run(void *opaque)
     assert(event->id < network_filters_count);
 
     qemu_netfilter_pass_to_next(network_filters[event->id]->netdev,
-        event->flags, &iov, 1, network_filters[event->id]);
+        &iov, 1, network_filters[event->id]);
 
     g_free(event->data);
     g_free(event);
@@ -85,7 +83,6 @@ void replay_event_net_save(void *opaque)
     NetEvent *event = opaque;
 
     replay_put_byte(event->id);
-    replay_put_dword(event->flags);
     replay_put_array(event->data, event->size);
 }
 
@@ -94,7 +91,6 @@ void *replay_event_net_load(void)
     NetEvent *event = g_new(NetEvent, 1);
 
     event->id = replay_get_byte();
-    event->flags = replay_get_dword();
     replay_get_array_alloc(&event->data, &event->size);
 
     return event;
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 07/21] tap: Shrink zeroed virtio-net header
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (5 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 06/21] net: Remove flag propagation Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 08/21] virtio-net: Copy header only when necessary Akihiko Odaki
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

tap prepends a zeroed virtio-net header when writing a packet to a
tap with virtio-net header enabled but not in use. This only happens
when s->host_vnet_hdr_len == sizeof(struct virtio_net_hdr).

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 net/tap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/tap.c b/net/tap.c
index ab4e5a0e91..bef680bdab 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -119,7 +119,7 @@ static ssize_t tap_receive_iov(NetClientState *nc, const struct iovec *iov,
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
     const struct iovec *iovp = iov;
     g_autofree struct iovec *iov_copy = NULL;
-    struct virtio_net_hdr_mrg_rxbuf hdr = { };
+    struct virtio_net_hdr hdr = { };
 
     if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
         iov_copy = g_new(struct iovec, iovcnt + 1);
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 08/21] virtio-net: Copy header only when necessary
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (6 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 07/21] tap: Shrink zeroed virtio-net header Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 09/21] virtio-net: Disable RSS on reset Akihiko Odaki
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

It is necessary to copy the header only for byte swapping. Worse, when
byte swapping is not needed, the header can be larger than the buffer
due to VIRTIO_NET_F_HASH_REPORT, which results in buffer overflow.

Copy the header only when byte swapping is needed.

Fixes: e22f0603fb ("virtio-net: reference implementation of hash report")
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 hw/net/virtio-net.c | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index e12176acb1..b6223031e1 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -359,7 +359,8 @@ static void virtio_net_vnet_endian_status(VirtIONet *n, uint8_t status)
          * can't do it, we fallback onto fixing the headers in the core
          * virtio-net code.
          */
-        n->needs_vnet_hdr_swap = virtio_net_set_vnet_endian(vdev, n->nic->ncs,
+        n->needs_vnet_hdr_swap = n->has_vnet_hdr &&
+                                 virtio_net_set_vnet_endian(vdev, n->nic->ncs,
                                                             queue_pairs, true);
     } else if (virtio_net_started(n, vdev->status)) {
         /* After using the device, we need to reset the network backend to
@@ -2709,7 +2710,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
             return -EINVAL;
         }
 
-        if (n->has_vnet_hdr) {
+        if (n->needs_vnet_hdr_swap) {
             if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) <
                 n->guest_hdr_len) {
                 virtio_error(vdev, "virtio-net header incorrect");
@@ -2717,19 +2718,16 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
                 g_free(elem);
                 return -EINVAL;
             }
-            if (n->needs_vnet_hdr_swap) {
-                virtio_net_hdr_swap(vdev, (void *) &mhdr);
-                sg2[0].iov_base = &mhdr;
-                sg2[0].iov_len = n->guest_hdr_len;
-                out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1,
-                                   out_sg, out_num,
-                                   n->guest_hdr_len, -1);
-                if (out_num == VIRTQUEUE_MAX_SIZE) {
-                    goto drop;
-                }
-                out_num += 1;
-                out_sg = sg2;
+            virtio_net_hdr_swap(vdev, (void *) &mhdr);
+            sg2[0].iov_base = &mhdr;
+            sg2[0].iov_len = n->guest_hdr_len;
+            out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1, out_sg, out_num,
+                               n->guest_hdr_len, -1);
+            if (out_num == VIRTQUEUE_MAX_SIZE) {
+                goto drop;
             }
+            out_num += 1;
+            out_sg = sg2;
         }
         /*
          * If host wants to see the guest header as is, we can
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 09/21] virtio-net: Disable RSS on reset
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (7 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 08/21] virtio-net: Copy header only when necessary Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 10/21] virtio-net: Unify the logic to update NIC state for RSS Akihiko Odaki
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki, Michael Tokarev

RSS is disabled by default.

Fixes: 590790297c ("virtio-net: implement RSS configuration command")
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
---
 hw/net/virtio-net.c | 70 +++++++++++++++++++++++----------------------
 1 file changed, 36 insertions(+), 34 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index b6223031e1..4c528baad9 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -599,40 +599,6 @@ static void virtio_net_queue_enable(VirtIODevice *vdev, uint32_t queue_index)
     }
 }
 
-static void virtio_net_reset(VirtIODevice *vdev)
-{
-    VirtIONet *n = VIRTIO_NET(vdev);
-    int i;
-
-    /* Reset back to compatibility mode */
-    n->promisc = 1;
-    n->allmulti = 0;
-    n->alluni = 0;
-    n->nomulti = 0;
-    n->nouni = 0;
-    n->nobcast = 0;
-    /* multiqueue is disabled by default */
-    n->curr_queue_pairs = 1;
-    timer_del(n->announce_timer.tm);
-    n->announce_timer.round = 0;
-    n->status &= ~VIRTIO_NET_S_ANNOUNCE;
-
-    /* Flush any MAC and VLAN filter table state */
-    n->mac_table.in_use = 0;
-    n->mac_table.first_multi = 0;
-    n->mac_table.multi_overflow = 0;
-    n->mac_table.uni_overflow = 0;
-    memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
-    memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac));
-    qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
-    memset(n->vlans, 0, MAX_VLAN >> 3);
-
-    /* Flush any async TX */
-    for (i = 0;  i < n->max_queue_pairs; i++) {
-        flush_or_purge_queued_packets(qemu_get_subqueue(n->nic, i));
-    }
-}
-
 static void peer_test_vnet_hdr(VirtIONet *n)
 {
     NetClientState *nc = qemu_get_queue(n->nic);
@@ -3805,6 +3771,42 @@ static void virtio_net_device_unrealize(DeviceState *dev)
     virtio_cleanup(vdev);
 }
 
+static void virtio_net_reset(VirtIODevice *vdev)
+{
+    VirtIONet *n = VIRTIO_NET(vdev);
+    int i;
+
+    /* Reset back to compatibility mode */
+    n->promisc = 1;
+    n->allmulti = 0;
+    n->alluni = 0;
+    n->nomulti = 0;
+    n->nouni = 0;
+    n->nobcast = 0;
+    /* multiqueue is disabled by default */
+    n->curr_queue_pairs = 1;
+    timer_del(n->announce_timer.tm);
+    n->announce_timer.round = 0;
+    n->status &= ~VIRTIO_NET_S_ANNOUNCE;
+
+    /* Flush any MAC and VLAN filter table state */
+    n->mac_table.in_use = 0;
+    n->mac_table.first_multi = 0;
+    n->mac_table.multi_overflow = 0;
+    n->mac_table.uni_overflow = 0;
+    memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
+    memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac));
+    qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
+    memset(n->vlans, 0, MAX_VLAN >> 3);
+
+    /* Flush any async TX */
+    for (i = 0;  i < n->max_queue_pairs; i++) {
+        flush_or_purge_queued_packets(qemu_get_subqueue(n->nic, i));
+    }
+
+    virtio_net_disable_rss(n);
+}
+
 static void virtio_net_instance_init(Object *obj)
 {
     VirtIONet *n = VIRTIO_NET(obj);
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 10/21] virtio-net: Unify the logic to update NIC state for RSS
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (8 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 09/21] virtio-net: Disable RSS on reset Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS Akihiko Odaki
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

The code to attach or detach the eBPF program to RSS were duplicated so
unify them into one function to save some code.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 hw/net/virtio-net.c | 90 ++++++++++++++++++---------------------------
 1 file changed, 36 insertions(+), 54 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 4c528baad9..5d4afd12b2 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1231,18 +1231,6 @@ static int virtio_net_handle_announce(VirtIONet *n, uint8_t cmd,
     }
 }
 
-static void virtio_net_detach_epbf_rss(VirtIONet *n);
-
-static void virtio_net_disable_rss(VirtIONet *n)
-{
-    if (n->rss_data.enabled) {
-        trace_virtio_net_rss_disable();
-    }
-    n->rss_data.enabled = false;
-
-    virtio_net_detach_epbf_rss(n);
-}
-
 static bool virtio_net_attach_ebpf_to_backend(NICState *nic, int prog_fd)
 {
     NetClientState *nc = qemu_get_peer(qemu_get_queue(nic), 0);
@@ -1290,6 +1278,40 @@ static void virtio_net_detach_epbf_rss(VirtIONet *n)
     virtio_net_attach_ebpf_to_backend(n->nic, -1);
 }
 
+static void virtio_net_commit_rss_config(VirtIONet *n)
+{
+    if (n->rss_data.enabled) {
+        n->rss_data.enabled_software_rss = n->rss_data.populate_hash;
+        if (n->rss_data.populate_hash) {
+            virtio_net_detach_epbf_rss(n);
+        } else if (!virtio_net_attach_epbf_rss(n)) {
+            if (get_vhost_net(qemu_get_queue(n->nic)->peer)) {
+                warn_report("Can't load eBPF RSS for vhost");
+            } else {
+                warn_report("Can't load eBPF RSS - fallback to software RSS");
+                n->rss_data.enabled_software_rss = true;
+            }
+        }
+
+        trace_virtio_net_rss_enable(n->rss_data.hash_types,
+                                    n->rss_data.indirections_len,
+                                    sizeof(n->rss_data.key));
+    } else {
+        virtio_net_detach_epbf_rss(n);
+        trace_virtio_net_rss_disable();
+    }
+}
+
+static void virtio_net_disable_rss(VirtIONet *n)
+{
+    if (!n->rss_data.enabled) {
+        return;
+    }
+
+    n->rss_data.enabled = false;
+    virtio_net_commit_rss_config(n);
+}
+
 static bool virtio_net_load_ebpf(VirtIONet *n)
 {
     if (!virtio_net_attach_ebpf_to_backend(n->nic, -1)) {
@@ -1418,28 +1440,7 @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
         goto error;
     }
     n->rss_data.enabled = true;
-
-    if (!n->rss_data.populate_hash) {
-        if (!virtio_net_attach_epbf_rss(n)) {
-            /* EBPF must be loaded for vhost */
-            if (get_vhost_net(qemu_get_queue(n->nic)->peer)) {
-                warn_report("Can't load eBPF RSS for vhost");
-                goto error;
-            }
-            /* fallback to software RSS */
-            warn_report("Can't load eBPF RSS - fallback to software RSS");
-            n->rss_data.enabled_software_rss = true;
-        }
-    } else {
-        /* use software RSS for hash populating */
-        /* and detach eBPF if was loaded before */
-        virtio_net_detach_epbf_rss(n);
-        n->rss_data.enabled_software_rss = true;
-    }
-
-    trace_virtio_net_rss_enable(n->rss_data.hash_types,
-                                n->rss_data.indirections_len,
-                                temp.b);
+    virtio_net_commit_rss_config(n);
     return queue_pairs;
 error:
     trace_virtio_net_rss_error(err_msg, err_value);
@@ -3035,26 +3036,7 @@ static int virtio_net_post_load_device(void *opaque, int version_id)
         }
     }
 
-    if (n->rss_data.enabled) {
-        n->rss_data.enabled_software_rss = n->rss_data.populate_hash;
-        if (!n->rss_data.populate_hash) {
-            if (!virtio_net_attach_epbf_rss(n)) {
-                if (get_vhost_net(qemu_get_queue(n->nic)->peer)) {
-                    warn_report("Can't post-load eBPF RSS for vhost");
-                } else {
-                    warn_report("Can't post-load eBPF RSS - "
-                                "fallback to software RSS");
-                    n->rss_data.enabled_software_rss = true;
-                }
-            }
-        }
-
-        trace_virtio_net_rss_enable(n->rss_data.hash_types,
-                                    n->rss_data.indirections_len,
-                                    sizeof(n->rss_data.key));
-    } else {
-        trace_virtio_net_rss_disable();
-    }
+    virtio_net_commit_rss_config(n);
     return 0;
 }
 
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (9 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 10/21] virtio-net: Unify the logic to update NIC state for RSS Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30 12:14   ` Yuri Benditovich
  2023-10-30  5:12 ` [PATCH v6 12/21] virtio-net: Enable software RSS Akihiko Odaki
                   ` (9 subsequent siblings)
  20 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

vhost requires eBPF for RSS. When eBPF is not available, virtio-net
implicitly disables RSS even if the user explicitly requests it. Return
an error instead of implicitly disabling RSS if RSS is requested but not
available.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 hw/net/virtio-net.c | 97 ++++++++++++++++++++++-----------------------
 1 file changed, 48 insertions(+), 49 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 5d4afd12b2..7bb91617d0 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -792,9 +792,6 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
         return features;
     }
 
-    if (!ebpf_rss_is_loaded(&n->ebpf_rss)) {
-        virtio_clear_feature(&features, VIRTIO_NET_F_RSS);
-    }
     features = vhost_net_get_features(get_vhost_net(nc->peer), features);
     vdev->backend_features = features;
 
@@ -3533,6 +3530,50 @@ static bool failover_hide_primary_device(DeviceListener *listener,
     return qatomic_read(&n->failover_primary_hidden);
 }
 
+static void virtio_net_device_unrealize(DeviceState *dev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VirtIONet *n = VIRTIO_NET(dev);
+    int i, max_queue_pairs;
+
+    if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) {
+        virtio_net_unload_ebpf(n);
+    }
+
+    /* This will stop vhost backend if appropriate. */
+    virtio_net_set_status(vdev, 0);
+
+    g_free(n->netclient_name);
+    n->netclient_name = NULL;
+    g_free(n->netclient_type);
+    n->netclient_type = NULL;
+
+    g_free(n->mac_table.macs);
+    g_free(n->vlans);
+
+    if (n->failover) {
+        qobject_unref(n->primary_opts);
+        device_listener_unregister(&n->primary_listener);
+        migration_remove_notifier(&n->migration_state);
+    } else {
+        assert(n->primary_opts == NULL);
+    }
+
+    max_queue_pairs = n->multiqueue ? n->max_queue_pairs : 1;
+    for (i = 0; i < max_queue_pairs; i++) {
+        virtio_net_del_queue(n, i);
+    }
+    /* delete also control vq */
+    virtio_del_queue(vdev, max_queue_pairs * 2);
+    qemu_announce_timer_del(&n->announce_timer, false);
+    g_free(n->vqs);
+    qemu_del_nic(n->nic);
+    virtio_net_rsc_cleanup(n);
+    g_free(n->rss_data.indirections_table);
+    net_rx_pkt_uninit(n->rx_pkt);
+    virtio_cleanup(vdev);
+}
+
 static void virtio_net_device_realize(DeviceState *dev, Error **errp)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
@@ -3704,53 +3745,11 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
 
     net_rx_pkt_init(&n->rx_pkt);
 
-    if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) {
-        virtio_net_load_ebpf(n);
-    }
-}
-
-static void virtio_net_device_unrealize(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VirtIONet *n = VIRTIO_NET(dev);
-    int i, max_queue_pairs;
-
-    if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) {
-        virtio_net_unload_ebpf(n);
+    if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS) &&
+        !virtio_net_load_ebpf(n)) {
+        error_setg(errp, "Can't load eBPF RSS");
+        virtio_net_device_unrealize(dev);
     }
-
-    /* This will stop vhost backend if appropriate. */
-    virtio_net_set_status(vdev, 0);
-
-    g_free(n->netclient_name);
-    n->netclient_name = NULL;
-    g_free(n->netclient_type);
-    n->netclient_type = NULL;
-
-    g_free(n->mac_table.macs);
-    g_free(n->vlans);
-
-    if (n->failover) {
-        qobject_unref(n->primary_opts);
-        device_listener_unregister(&n->primary_listener);
-        migration_remove_notifier(&n->migration_state);
-    } else {
-        assert(n->primary_opts == NULL);
-    }
-
-    max_queue_pairs = n->multiqueue ? n->max_queue_pairs : 1;
-    for (i = 0; i < max_queue_pairs; i++) {
-        virtio_net_del_queue(n, i);
-    }
-    /* delete also control vq */
-    virtio_del_queue(vdev, max_queue_pairs * 2);
-    qemu_announce_timer_del(&n->announce_timer, false);
-    g_free(n->vqs);
-    qemu_del_nic(n->nic);
-    virtio_net_rsc_cleanup(n);
-    g_free(n->rss_data.indirections_table);
-    net_rx_pkt_uninit(n->rx_pkt);
-    virtio_cleanup(vdev);
 }
 
 static void virtio_net_reset(VirtIODevice *vdev)
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 12/21] virtio-net: Enable software RSS
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (10 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30 12:42   ` Yuri Benditovich
  2023-10-30  5:12 ` [PATCH v6 13/21] virtio-net: Always set populate_hash Akihiko Odaki
                   ` (8 subsequent siblings)
  20 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

virtio-net implements software RSS but does not enable it. Enable it
when RSS is requested, but the eBPF implementation is not available.
We also check if vhost is in use in such a case since software RSS is
incompatible with vhost. A warning will be emitted when falling back to
software RSS since it provides no performance benefit.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 hw/net/virtio-net.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 7bb91617d0..1fa020d905 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1260,10 +1260,12 @@ static bool virtio_net_attach_epbf_rss(VirtIONet *n)
 
     if (!ebpf_rss_set_all(&n->ebpf_rss, &config,
                           n->rss_data.indirections_table, n->rss_data.key)) {
+        warn_report("Failed to configure eBPF RSS");
         return false;
     }
 
     if (!virtio_net_attach_ebpf_to_backend(n->nic, n->ebpf_rss.program_fd)) {
+        warn_report("Failed to attach eBPF to backend");
         return false;
     }
 
@@ -1278,16 +1280,10 @@ static void virtio_net_detach_epbf_rss(VirtIONet *n)
 static void virtio_net_commit_rss_config(VirtIONet *n)
 {
     if (n->rss_data.enabled) {
-        n->rss_data.enabled_software_rss = n->rss_data.populate_hash;
+        n->rss_data.enabled_software_rss = n->rss_data.populate_hash ||
+                                           !virtio_net_attach_epbf_rss(n);
         if (n->rss_data.populate_hash) {
             virtio_net_detach_epbf_rss(n);
-        } else if (!virtio_net_attach_epbf_rss(n)) {
-            if (get_vhost_net(qemu_get_queue(n->nic)->peer)) {
-                warn_report("Can't load eBPF RSS for vhost");
-            } else {
-                warn_report("Can't load eBPF RSS - fallback to software RSS");
-                n->rss_data.enabled_software_rss = true;
-            }
         }
 
         trace_virtio_net_rss_enable(n->rss_data.hash_types,
@@ -3747,8 +3743,13 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
 
     if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS) &&
         !virtio_net_load_ebpf(n)) {
-        error_setg(errp, "Can't load eBPF RSS");
-        virtio_net_device_unrealize(dev);
+        if (get_vhost_net(nc->peer)) {
+            error_setg(errp, "Can't load eBPF RSS for vhost");
+            virtio_net_device_unrealize(dev);
+            return;
+        }
+
+        warn_report_once("Can't load eBPF RSS - fallback to software RSS");
     }
 }
 
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 13/21] virtio-net: Always set populate_hash
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (11 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 12/21] virtio-net: Enable software RSS Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30 19:02   ` Zhang, Chen
  2023-10-30  5:12 ` [PATCH v6 14/21] virtio-net: Do not write hashes to peer buffer Akihiko Odaki
                   ` (7 subsequent siblings)
  20 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

The member is not cleared during reset so may have a stale value.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 hw/net/virtio-net.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 1fa020d905..0fe75b3c08 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -650,6 +650,7 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
         n->guest_hdr_len = n->mergeable_rx_bufs ?
             sizeof(struct virtio_net_hdr_mrg_rxbuf) :
             sizeof(struct virtio_net_hdr);
+        n->rss_data.populate_hash = false;
     }
 
     for (i = 0; i < n->max_queue_pairs; i++) {
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 14/21] virtio-net: Do not write hashes to peer buffer
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (12 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 13/21] virtio-net: Always set populate_hash Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 15/21] virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT Akihiko Odaki
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

The peer buffer is qualified with const and not meant to be modified.
It also prevents enabling VIRTIO_NET_F_HASH_REPORT for peers without
virtio-net header support.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 hw/net/virtio-net.c | 36 +++++++++++++++++-------------------
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 0fe75b3c08..e30105884c 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1786,16 +1786,9 @@ static uint8_t virtio_net_get_hash_type(bool hasip4,
     return 0xff;
 }
 
-static void virtio_set_packet_hash(const uint8_t *buf, uint8_t report,
-                                   uint32_t hash)
-{
-    struct virtio_net_hdr_v1_hash *hdr = (void *)buf;
-    hdr->hash_value = hash;
-    hdr->hash_report = report;
-}
-
 static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
-                                  size_t size)
+                                  size_t size,
+                                  struct virtio_net_hdr_v1_hash *hdr)
 {
     VirtIONet *n = qemu_get_nic_opaque(nc);
     unsigned int index = nc->queue_index, new_index = index;
@@ -1826,7 +1819,8 @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
                                              n->rss_data.hash_types);
     if (net_hash_type > NetPktRssIpV6UdpEx) {
         if (n->rss_data.populate_hash) {
-            virtio_set_packet_hash(buf, VIRTIO_NET_HASH_REPORT_NONE, 0);
+            hdr->hash_value = VIRTIO_NET_HASH_REPORT_NONE;
+            hdr->hash_report = 0;
         }
         return n->rss_data.redirect ? n->rss_data.default_queue : -1;
     }
@@ -1834,7 +1828,8 @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
     hash = net_rx_pkt_calc_rss_hash(pkt, net_hash_type, n->rss_data.key);
 
     if (n->rss_data.populate_hash) {
-        virtio_set_packet_hash(buf, reports[net_hash_type], hash);
+        hdr->hash_value = hash;
+        hdr->hash_report = reports[net_hash_type];
     }
 
     if (n->rss_data.redirect) {
@@ -1854,7 +1849,7 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
     VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE];
     size_t lens[VIRTQUEUE_MAX_SIZE];
     struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
-    struct virtio_net_hdr_mrg_rxbuf mhdr;
+    struct virtio_net_hdr_v1_hash extra_hdr;
     unsigned mhdr_cnt = 0;
     size_t offset, i, guest_offset, j;
     ssize_t err;
@@ -1864,7 +1859,7 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
     }
 
     if (!no_rss && n->rss_data.enabled && n->rss_data.enabled_software_rss) {
-        int index = virtio_net_process_rss(nc, buf, size);
+        int index = virtio_net_process_rss(nc, buf, size, &extra_hdr);
         if (index >= 0) {
             NetClientState *nc2 = qemu_get_subqueue(n->nic, index);
             return virtio_net_receive_rcu(nc2, buf, size, true);
@@ -1924,15 +1919,17 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
             if (n->mergeable_rx_bufs) {
                 mhdr_cnt = iov_copy(mhdr_sg, ARRAY_SIZE(mhdr_sg),
                                     sg, elem->in_num,
-                                    offsetof(typeof(mhdr), num_buffers),
-                                    sizeof(mhdr.num_buffers));
+                                    offsetof(typeof(extra_hdr), hdr.num_buffers),
+                                    sizeof(extra_hdr.hdr.num_buffers));
             }
 
             receive_header(n, sg, elem->in_num, buf, size);
             if (n->rss_data.populate_hash) {
-                offset = sizeof(mhdr);
+                offset = offsetof(typeof(extra_hdr), hash_value);
                 iov_from_buf(sg, elem->in_num, offset,
-                             buf + offset, n->host_hdr_len - sizeof(mhdr));
+                             (char *)&extra_hdr + offset,
+                             sizeof(extra_hdr.hash_value) +
+                             sizeof(extra_hdr.hash_report));
             }
             offset = n->host_hdr_len;
             total += n->guest_hdr_len;
@@ -1962,10 +1959,11 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
     }
 
     if (mhdr_cnt) {
-        virtio_stw_p(vdev, &mhdr.num_buffers, i);
+        virtio_stw_p(vdev, &extra_hdr.hdr.num_buffers, i);
         iov_from_buf(mhdr_sg, mhdr_cnt,
                      0,
-                     &mhdr.num_buffers, sizeof mhdr.num_buffers);
+                     &extra_hdr.hdr.num_buffers,
+                     sizeof extra_hdr.hdr.num_buffers);
     }
 
     for (j = 0; j < i; j++) {
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 15/21] virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (13 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 14/21] virtio-net: Do not write hashes to peer buffer Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-11-03 13:26   ` Yuri Benditovich
  2023-10-30  5:12 ` [PATCH v6 16/21] ebpf: Fix RSS error handling Akihiko Odaki
                   ` (5 subsequent siblings)
  20 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

virtio-net can report hash values even if the peer does not have a
virtio-net header.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 hw/net/virtio-net.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index e30105884c..bdb4579f98 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -774,8 +774,6 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
         virtio_clear_feature(&features, VIRTIO_NET_F_HOST_USO);
         virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_USO4);
         virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_USO6);
-
-        virtio_clear_feature(&features, VIRTIO_NET_F_HASH_REPORT);
     }
 
     if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 16/21] ebpf: Fix RSS error handling
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (14 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 15/21] virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 17/21] ebpf: Use standard section name Akihiko Odaki
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

calculate_rss_hash() was using hash value 0 to tell if it calculated
a hash, but the hash value may be 0 on a rare occasion. Have a
distinct bool value for correctness.

Fixes: f3fa412de2 ("ebpf: Added eBPF RSS program.")
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 tools/ebpf/rss.bpf.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/tools/ebpf/rss.bpf.c b/tools/ebpf/rss.bpf.c
index 20f227e2ac..667ea6899e 100644
--- a/tools/ebpf/rss.bpf.c
+++ b/tools/ebpf/rss.bpf.c
@@ -377,18 +377,19 @@ error:
     return err;
 }
 
-static inline __u32 calculate_rss_hash(struct __sk_buff *skb,
-        struct rss_config_t *config, struct toeplitz_key_data_t *toe)
+static inline bool calculate_rss_hash(struct __sk_buff *skb,
+                                      struct rss_config_t *config,
+                                      struct toeplitz_key_data_t *toe,
+                                      __u32 *result)
 {
     __u8 rss_input[HASH_CALCULATION_BUFFER_SIZE] = {};
     size_t bytes_written = 0;
-    __u32 result = 0;
     int err = 0;
     struct packet_hash_info_t packet_info = {};
 
     err = parse_packet(skb, &packet_info);
     if (err) {
-        return 0;
+        return false;
     }
 
     if (packet_info.is_ipv4) {
@@ -521,11 +522,13 @@ static inline __u32 calculate_rss_hash(struct __sk_buff *skb,
         }
     }
 
-    if (bytes_written) {
-        net_toeplitz_add(&result, rss_input, bytes_written, toe);
+    if (!bytes_written) {
+        return false;
     }
 
-    return result;
+    net_toeplitz_add(result, rss_input, bytes_written, toe);
+
+    return true;
 }
 
 SEC("tun_rss_steering")
@@ -546,8 +549,7 @@ int tun_rss_steering_prog(struct __sk_buff *skb)
             return config->default_queue;
         }
 
-        hash = calculate_rss_hash(skb, config, toe);
-        if (hash) {
+        if (calculate_rss_hash(skb, config, toe, &hash)) {
             __u32 table_idx = hash % config->indirections_len;
             __u16 *queue = 0;
 
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 17/21] ebpf: Use standard section name
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (15 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 16/21] ebpf: Fix RSS error handling Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 18/21] ebpf: Simplify error handling Akihiko Odaki
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

It makes easier to play with bpftool by allowing it to infer the program
type. It also makes it unnecessary to set the program type manually
when loading the program in ebpf_rss_load().

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 ebpf/rss.bpf.skeleton.h | 1514 ++++++++++++++++++++-------------------
 ebpf/ebpf_rss.c         |    2 -
 tools/ebpf/rss.bpf.c    |    2 +-
 3 files changed, 760 insertions(+), 758 deletions(-)

diff --git a/ebpf/rss.bpf.skeleton.h b/ebpf/rss.bpf.skeleton.h
index 18eb2adb12..f011c3258e 100644
--- a/ebpf/rss.bpf.skeleton.h
+++ b/ebpf/rss.bpf.skeleton.h
@@ -176,796 +176,800 @@ err:
 
 static inline const void *rss_bpf__elf_bytes(size_t *sz)
 {
-	*sz = 20440;
+	*sz = 20520;
 	return (const void *)"\
 \x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\x98\x4c\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0d\0\
-\x01\0\xbf\x19\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\x54\xff\0\0\0\0\xbf\xa7\
-\0\0\0\0\0\0\x07\x07\0\0\x54\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\xe8\x4c\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0d\0\
+\x01\0\xbf\x19\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\x4c\xff\0\0\0\0\xbf\xa7\
+\0\0\0\0\0\0\x07\x07\0\0\x4c\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
 \xbf\x72\0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\xbf\x06\0\0\0\0\0\0\x18\x01\0\0\0\0\0\
 \0\0\0\0\0\0\0\0\0\xbf\x72\0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\xbf\x08\0\0\0\0\0\0\
-\x18\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\x15\x06\x67\x02\0\0\0\0\xbf\x87\0\0\
-\0\0\0\0\x15\x07\x65\x02\0\0\0\0\x71\x61\0\0\0\0\0\0\x55\x01\x01\0\0\0\0\0\x05\
-\0\x5e\x02\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xc8\xff\0\0\0\0\x7b\x1a\xc0\xff\
-\0\0\0\0\x7b\x1a\xb8\xff\0\0\0\0\x7b\x1a\xb0\xff\0\0\0\0\x7b\x1a\xa8\xff\0\0\0\
-\0\x63\x1a\xa0\xff\0\0\0\0\x7b\x1a\x98\xff\0\0\0\0\x7b\x1a\x90\xff\0\0\0\0\x7b\
-\x1a\x88\xff\0\0\0\0\x7b\x1a\x80\xff\0\0\0\0\x7b\x1a\x78\xff\0\0\0\0\x7b\x1a\
-\x70\xff\0\0\0\0\x7b\x1a\x68\xff\0\0\0\0\x7b\x1a\x60\xff\0\0\0\0\x7b\x1a\x58\
-\xff\0\0\0\0\x15\x09\x4d\x02\0\0\0\0\x6b\x1a\xd0\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\
-\0\x07\x03\0\0\xd0\xff\xff\xff\xbf\x91\0\0\0\0\0\0\xb7\x02\0\0\x0c\0\0\0\xb7\
+\x18\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\x15\x06\x62\x02\0\0\0\0\xbf\x87\0\0\
+\0\0\0\0\x15\x07\x60\x02\0\0\0\0\x71\x61\0\0\0\0\0\0\x55\x01\x01\0\0\0\0\0\x05\
+\0\x59\x02\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xc0\xff\0\0\0\0\x7b\x1a\xb8\xff\
+\0\0\0\0\x7b\x1a\xb0\xff\0\0\0\0\x7b\x1a\xa8\xff\0\0\0\0\x7b\x1a\xa0\xff\0\0\0\
+\0\x63\x1a\x98\xff\0\0\0\0\x7b\x1a\x90\xff\0\0\0\0\x7b\x1a\x88\xff\0\0\0\0\x7b\
+\x1a\x80\xff\0\0\0\0\x7b\x1a\x78\xff\0\0\0\0\x7b\x1a\x70\xff\0\0\0\0\x7b\x1a\
+\x68\xff\0\0\0\0\x7b\x1a\x60\xff\0\0\0\0\x7b\x1a\x58\xff\0\0\0\0\x7b\x1a\x50\
+\xff\0\0\0\0\x15\x09\x48\x02\0\0\0\0\x6b\x1a\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\
+\0\x07\x03\0\0\xc8\xff\xff\xff\xbf\x91\0\0\0\0\0\0\xb7\x02\0\0\x0c\0\0\0\xb7\
 \x04\0\0\x02\0\0\0\xb7\x05\0\0\0\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\
-\x77\0\0\0\x20\0\0\0\x55\0\x42\x02\0\0\0\0\xb7\x02\0\0\x10\0\0\0\x69\xa1\xd0\
+\x77\0\0\0\x20\0\0\0\x55\0\x3d\x02\0\0\0\0\xb7\x02\0\0\x10\0\0\0\x69\xa1\xc8\
 \xff\0\0\0\0\xbf\x13\0\0\0\0\0\0\xdc\x03\0\0\x10\0\0\0\x15\x03\x02\0\0\x81\0\0\
 \x55\x03\x0b\0\xa8\x88\0\0\xb7\x02\0\0\x14\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\
-\0\xd0\xff\xff\xff\xbf\x91\0\0\0\0\0\0\xb7\x04\0\0\x02\0\0\0\xb7\x05\0\0\0\0\0\
-\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x55\0\x32\x02\0\
-\0\0\0\x69\xa1\xd0\xff\0\0\0\0\x15\x01\x30\x02\0\0\0\0\x7b\x7a\x38\xff\0\0\0\0\
-\x7b\x9a\x40\xff\0\0\0\0\x15\x01\x55\0\x86\xdd\0\0\x55\x01\x39\0\x08\0\0\0\xb7\
-\x07\0\0\x01\0\0\0\x73\x7a\x58\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xe0\xff\
-\0\0\0\0\x7b\x1a\xd8\xff\0\0\0\0\x7b\x1a\xd0\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\
-\x07\x03\0\0\xd0\xff\xff\xff\x79\xa1\x40\xff\0\0\0\0\xb7\x02\0\0\0\0\0\0\xb7\
+\0\xc8\xff\xff\xff\xbf\x91\0\0\0\0\0\0\xb7\x04\0\0\x02\0\0\0\xb7\x05\0\0\0\0\0\
+\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x55\0\x2d\x02\0\
+\0\0\0\x69\xa1\xc8\xff\0\0\0\0\x15\x01\x2b\x02\0\0\0\0\x7b\x7a\x30\xff\0\0\0\0\
+\x7b\x9a\x38\xff\0\0\0\0\x15\x01\x55\0\x86\xdd\0\0\x55\x01\x39\0\x08\0\0\0\xb7\
+\x07\0\0\x01\0\0\0\x73\x7a\x50\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xd8\xff\
+\0\0\0\0\x7b\x1a\xd0\xff\0\0\0\0\x7b\x1a\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\
+\x07\x03\0\0\xc8\xff\xff\xff\x79\xa1\x38\xff\0\0\0\0\xb7\x02\0\0\0\0\0\0\xb7\
 \x04\0\0\x14\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\
-\0\x77\0\0\0\x20\0\0\0\x55\0\x1c\x02\0\0\0\0\x69\xa1\xd6\xff\0\0\0\0\x55\x01\
-\x01\0\0\0\0\0\xb7\x07\0\0\0\0\0\0\x61\xa1\xdc\xff\0\0\0\0\x63\x1a\x64\xff\0\0\
-\0\0\x61\xa1\xe0\xff\0\0\0\0\x63\x1a\x68\xff\0\0\0\0\x71\xa9\xd9\xff\0\0\0\0\
-\x73\x7a\x5e\xff\0\0\0\0\x71\xa1\xd0\xff\0\0\0\0\x67\x01\0\0\x02\0\0\0\x57\x01\
-\0\0\x3c\0\0\0\x7b\x1a\x48\xff\0\0\0\0\xbf\x91\0\0\0\0\0\0\x57\x01\0\0\xff\0\0\
+\0\x77\0\0\0\x20\0\0\0\x55\0\x17\x02\0\0\0\0\x69\xa1\xce\xff\0\0\0\0\x55\x01\
+\x01\0\0\0\0\0\xb7\x07\0\0\0\0\0\0\x61\xa1\xd4\xff\0\0\0\0\x63\x1a\x5c\xff\0\0\
+\0\0\x61\xa1\xd8\xff\0\0\0\0\x63\x1a\x60\xff\0\0\0\0\x71\xa9\xd1\xff\0\0\0\0\
+\x73\x7a\x56\xff\0\0\0\0\x71\xa1\xc8\xff\0\0\0\0\x67\x01\0\0\x02\0\0\0\x57\x01\
+\0\0\x3c\0\0\0\x7b\x1a\x40\xff\0\0\0\0\xbf\x91\0\0\0\0\0\0\x57\x01\0\0\xff\0\0\
 \0\x15\x01\x19\0\0\0\0\0\x57\x07\0\0\xff\0\0\0\x55\x07\x17\0\0\0\0\0\x57\x09\0\
 \0\xff\0\0\0\x15\x09\x5a\x01\x11\0\0\0\x55\x09\x14\0\x06\0\0\0\xb7\x01\0\0\x01\
-\0\0\0\x73\x1a\x5b\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xe0\xff\0\0\0\0\x7b\
-\x1a\xd8\xff\0\0\0\0\x7b\x1a\xd0\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\
-\xd0\xff\xff\xff\x79\xa1\x40\xff\0\0\0\0\x79\xa2\x48\xff\0\0\0\0\xb7\x04\0\0\
+\0\0\0\x73\x1a\x53\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xd8\xff\0\0\0\0\x7b\
+\x1a\xd0\xff\0\0\0\0\x7b\x1a\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\
+\xc8\xff\xff\xff\x79\xa1\x38\xff\0\0\0\0\x79\xa2\x40\xff\0\0\0\0\xb7\x04\0\0\
 \x14\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\
-\0\0\x20\0\0\0\x55\0\xf7\x01\0\0\0\0\x69\xa1\xd0\xff\0\0\0\0\x6b\x1a\x60\xff\0\
-\0\0\0\x69\xa1\xd2\xff\0\0\0\0\x6b\x1a\x62\xff\0\0\0\0\x71\xa1\x58\xff\0\0\0\0\
+\0\0\x20\0\0\0\x55\0\xf2\x01\0\0\0\0\x69\xa1\xc8\xff\0\0\0\0\x6b\x1a\x58\xff\0\
+\0\0\0\x69\xa1\xca\xff\0\0\0\0\x6b\x1a\x5a\xff\0\0\0\0\x71\xa1\x50\xff\0\0\0\0\
 \x15\x01\xdb\0\0\0\0\0\x71\x62\x03\0\0\0\0\0\x67\x02\0\0\x08\0\0\0\x71\x61\x02\
-\0\0\0\0\0\x4f\x12\0\0\0\0\0\0\x71\x63\x04\0\0\0\0\0\x71\x61\x05\0\0\0\0\0\x67\
-\x01\0\0\x08\0\0\0\x4f\x31\0\0\0\0\0\0\x67\x01\0\0\x10\0\0\0\x4f\x21\0\0\0\0\0\
-\0\x71\xa2\x5b\xff\0\0\0\0\x79\xa0\x38\xff\0\0\0\0\x15\x02\x0c\x01\0\0\0\0\xbf\
-\x12\0\0\0\0\0\0\x57\x02\0\0\x02\0\0\0\x15\x02\x09\x01\0\0\0\0\x61\xa1\x64\xff\
-\0\0\0\0\x63\x1a\xa8\xff\0\0\0\0\x61\xa1\x68\xff\0\0\0\0\x63\x1a\xac\xff\0\0\0\
-\0\x69\xa1\x60\xff\0\0\0\0\x6b\x1a\xb0\xff\0\0\0\0\x69\xa1\x62\xff\0\0\0\0\x6b\
-\x1a\xb2\xff\0\0\0\0\x05\0\x6b\x01\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x59\
-\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x7b\x1a\xf0\xff\0\0\0\0\x7b\x1a\xe8\xff\0\0\0\
-\0\x7b\x1a\xe0\xff\0\0\0\0\x7b\x1a\xd8\xff\0\0\0\0\x7b\x1a\xd0\xff\0\0\0\0\xbf\
-\xa3\0\0\0\0\0\0\x07\x03\0\0\xd0\xff\xff\xff\xb7\x01\0\0\x28\0\0\0\x7b\x1a\x48\
+\0\0\0\0\0\x4f\x12\0\0\0\0\0\0\x71\x63\x04\0\0\0\0\0\x67\x03\0\0\x10\0\0\0\x71\
+\x61\x05\0\0\0\0\0\x67\x01\0\0\x18\0\0\0\x4f\x31\0\0\0\0\0\0\x4f\x21\0\0\0\0\0\
+\0\x71\xa2\x53\xff\0\0\0\0\x79\xa0\x30\xff\0\0\0\0\x15\x02\x0c\x01\0\0\0\0\xbf\
+\x12\0\0\0\0\0\0\x57\x02\0\0\x02\0\0\0\x15\x02\x09\x01\0\0\0\0\x61\xa1\x5c\xff\
+\0\0\0\0\x63\x1a\xa0\xff\0\0\0\0\x61\xa1\x60\xff\0\0\0\0\x63\x1a\xa4\xff\0\0\0\
+\0\x69\xa1\x58\xff\0\0\0\0\x6b\x1a\xa8\xff\0\0\0\0\x69\xa1\x5a\xff\0\0\0\0\x6b\
+\x1a\xaa\xff\0\0\0\0\x05\0\x6a\x01\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x51\
+\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x7b\x1a\xe8\xff\0\0\0\0\x7b\x1a\xe0\xff\0\0\0\
+\0\x7b\x1a\xd8\xff\0\0\0\0\x7b\x1a\xd0\xff\0\0\0\0\x7b\x1a\xc8\xff\0\0\0\0\xbf\
+\xa3\0\0\0\0\0\0\x07\x03\0\0\xc8\xff\xff\xff\xb7\x01\0\0\x28\0\0\0\x7b\x1a\x40\
 \xff\0\0\0\0\xbf\x91\0\0\0\0\0\0\xb7\x02\0\0\0\0\0\0\xb7\x04\0\0\x28\0\0\0\xb7\
 \x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\
-\x55\0\xfe\0\0\0\0\0\x79\xa1\xe0\xff\0\0\0\0\x63\x1a\x6c\xff\0\0\0\0\x77\x01\0\
-\0\x20\0\0\0\x63\x1a\x70\xff\0\0\0\0\x79\xa1\xd8\xff\0\0\0\0\x63\x1a\x64\xff\0\
-\0\0\0\x77\x01\0\0\x20\0\0\0\x63\x1a\x68\xff\0\0\0\0\x79\xa1\xe8\xff\0\0\0\0\
-\x63\x1a\x74\xff\0\0\0\0\x77\x01\0\0\x20\0\0\0\x63\x1a\x78\xff\0\0\0\0\x79\xa1\
-\xf0\xff\0\0\0\0\x63\x1a\x7c\xff\0\0\0\0\x77\x01\0\0\x20\0\0\0\x63\x1a\x80\xff\
-\0\0\0\0\x71\xa9\xd6\xff\0\0\0\0\x25\x09\x13\x01\x3c\0\0\0\xb7\x01\0\0\x01\0\0\
+\x55\0\xfe\0\0\0\0\0\x79\xa1\xd8\xff\0\0\0\0\x63\x1a\x64\xff\0\0\0\0\x77\x01\0\
+\0\x20\0\0\0\x63\x1a\x68\xff\0\0\0\0\x79\xa1\xd0\xff\0\0\0\0\x63\x1a\x5c\xff\0\
+\0\0\0\x77\x01\0\0\x20\0\0\0\x63\x1a\x60\xff\0\0\0\0\x79\xa1\xe0\xff\0\0\0\0\
+\x63\x1a\x6c\xff\0\0\0\0\x77\x01\0\0\x20\0\0\0\x63\x1a\x70\xff\0\0\0\0\x79\xa1\
+\xe8\xff\0\0\0\0\x63\x1a\x74\xff\0\0\0\0\x77\x01\0\0\x20\0\0\0\x63\x1a\x78\xff\
+\0\0\0\0\x71\xa9\xce\xff\0\0\0\0\x25\x09\x13\x01\x3c\0\0\0\xb7\x01\0\0\x01\0\0\
 \0\x6f\x91\0\0\0\0\0\0\x18\x02\0\0\x01\0\0\0\0\0\0\0\0\x18\0\x1c\x5f\x21\0\0\0\
 \0\0\0\x55\x01\x01\0\0\0\0\0\x05\0\x0c\x01\0\0\0\0\xb7\x01\0\0\0\0\0\0\x6b\x1a\
-\xfe\xff\0\0\0\0\xb7\x01\0\0\x28\0\0\0\x7b\x1a\x48\xff\0\0\0\0\xbf\xa1\0\0\0\0\
-\0\0\x07\x01\0\0\x94\xff\xff\xff\x7b\x1a\x20\xff\0\0\0\0\xbf\xa1\0\0\0\0\0\0\
-\x07\x01\0\0\x84\xff\xff\xff\x7b\x1a\x18\xff\0\0\0\0\x18\x07\0\0\x01\0\0\0\0\0\
-\0\0\0\x18\0\x1c\xb7\x02\0\0\0\0\0\0\x7b\x8a\x28\xff\0\0\0\0\x7b\x2a\x30\xff\0\
-\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\xfe\xff\xff\xff\x79\xa1\x40\xff\0\0\0\0\
-\x79\xa2\x48\xff\0\0\0\0\xb7\x04\0\0\x02\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\
-\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x15\0\x01\0\0\0\0\0\x05\0\
-\x91\x01\0\0\0\0\xbf\x91\0\0\0\0\0\0\x15\x01\x26\0\x3c\0\0\0\x15\x01\x5f\0\x2c\
-\0\0\0\x55\x01\x60\0\x2b\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xf8\xff\0\0\0\0\xbf\
-\xa3\0\0\0\0\0\0\x07\x03\0\0\xf8\xff\xff\xff\x79\xa7\x40\xff\0\0\0\0\xbf\x71\0\
-\0\0\0\0\0\x79\xa2\x48\xff\0\0\0\0\xb7\x04\0\0\x04\0\0\0\xb7\x05\0\0\x01\0\0\0\
-\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\
-\0\0\0\x55\x01\x06\x01\0\0\0\0\x71\xa1\xfa\xff\0\0\0\0\x55\x01\x11\0\x02\0\0\0\
-\x71\xa1\xf9\xff\0\0\0\0\x55\x01\x0f\0\x02\0\0\0\x71\xa1\xfb\xff\0\0\0\0\x55\
-\x01\x0d\0\x01\0\0\0\x79\xa2\x48\xff\0\0\0\0\x07\x02\0\0\x08\0\0\0\xbf\x71\0\0\
-\0\0\0\0\x79\xa3\x20\xff\0\0\0\0\xb7\x04\0\0\x10\0\0\0\xb7\x05\0\0\x01\0\0\0\
-\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\
-\0\0\0\x55\x01\xf5\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x5d\xff\0\0\0\0\x18\
-\x07\0\0\x01\0\0\0\0\0\0\0\0\x18\0\x1c\x05\0\x3c\0\0\0\0\0\xb7\x08\0\0\x02\0\0\
-\0\xb7\x07\0\0\0\0\0\0\x6b\x7a\xf8\xff\0\0\0\0\x05\0\x13\0\0\0\0\0\x0f\x81\0\0\
-\0\0\0\0\xbf\x12\0\0\0\0\0\0\x07\x02\0\0\x01\0\0\0\x71\xa3\xff\xff\0\0\0\0\x67\
-\x03\0\0\x03\0\0\0\x3d\x32\x09\0\0\0\0\0\xbf\x72\0\0\0\0\0\0\x07\x02\0\0\x01\0\
-\0\0\x67\x07\0\0\x20\0\0\0\xbf\x73\0\0\0\0\0\0\x77\x03\0\0\x20\0\0\0\xbf\x27\0\
-\0\0\0\0\0\xbf\x18\0\0\0\0\0\0\xb7\x01\0\0\x1d\0\0\0\x2d\x31\x04\0\0\0\0\0\x79\
-\xa8\x28\xff\0\0\0\0\x18\x07\0\0\x01\0\0\0\0\0\0\0\0\x18\0\x1c\x05\0\x25\0\0\0\
-\0\0\xbf\x89\0\0\0\0\0\0\x79\xa1\x48\xff\0\0\0\0\x0f\x19\0\0\0\0\0\0\xbf\xa3\0\
-\0\0\0\0\0\x07\x03\0\0\xf8\xff\xff\xff\x79\xa1\x40\xff\0\0\0\0\xbf\x92\0\0\0\0\
-\0\0\xb7\x04\0\0\x02\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\
-\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\x79\0\0\0\0\0\
-\x71\xa2\xf8\xff\0\0\0\0\x55\x02\x0e\0\xc9\0\0\0\x07\x09\0\0\x02\0\0\0\x79\xa1\
-\x40\xff\0\0\0\0\xbf\x92\0\0\0\0\0\0\x79\xa3\x18\xff\0\0\0\0\xb7\x04\0\0\x10\0\
-\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\x01\0\0\
-\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\x6c\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\
-\x73\x1a\x5c\xff\0\0\0\0\x05\0\xde\xff\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\x02\
-\xcd\xff\0\0\0\0\x71\xa1\xf9\xff\0\0\0\0\x07\x01\0\0\x02\0\0\0\x05\0\xca\xff\0\
-\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x5e\xff\0\0\0\0\x71\xa1\xff\xff\0\0\0\0\
-\x67\x01\0\0\x03\0\0\0\x79\xa2\x48\xff\0\0\0\0\x0f\x12\0\0\0\0\0\0\x07\x02\0\0\
-\x08\0\0\0\x7b\x2a\x48\xff\0\0\0\0\x71\xa9\xfe\xff\0\0\0\0\x79\xa2\x30\xff\0\0\
-\0\0\x25\x09\x0c\0\x3c\0\0\0\xb7\x01\0\0\x01\0\0\0\x6f\x91\0\0\0\0\0\0\x5f\x71\
-\0\0\0\0\0\0\x55\x01\x01\0\0\0\0\0\x05\0\x07\0\0\0\0\0\x07\x02\0\0\x01\0\0\0\
-\xbf\x21\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\x7d\
-\xff\x0b\0\0\0\x71\xa7\x5e\xff\0\0\0\0\x05\0\x09\xff\0\0\0\0\x15\x09\xf8\xff\
-\x87\0\0\0\x05\0\xfc\xff\0\0\0\0\x71\xa1\x59\xff\0\0\0\0\x79\xa0\x38\xff\0\0\0\
-\0\x15\x01\x13\x01\0\0\0\0\x71\x62\x03\0\0\0\0\0\x67\x02\0\0\x08\0\0\0\x71\x61\
-\x02\0\0\0\0\0\x4f\x12\0\0\0\0\0\0\x71\x63\x04\0\0\0\0\0\x71\x61\x05\0\0\0\0\0\
-\x67\x01\0\0\x08\0\0\0\x4f\x31\0\0\0\0\0\0\x67\x01\0\0\x10\0\0\0\x4f\x21\0\0\0\
-\0\0\0\x71\xa2\x5b\xff\0\0\0\0\x15\x02\x42\0\0\0\0\0\xbf\x12\0\0\0\0\0\0\x57\
+\xf8\xff\0\0\0\0\xb7\x01\0\0\x28\0\0\0\x7b\x1a\x40\xff\0\0\0\0\xbf\xa1\0\0\0\0\
+\0\0\x07\x01\0\0\x8c\xff\xff\xff\x7b\x1a\x18\xff\0\0\0\0\xbf\xa1\0\0\0\0\0\0\
+\x07\x01\0\0\x7c\xff\xff\xff\x7b\x1a\x10\xff\0\0\0\0\x18\x07\0\0\x01\0\0\0\0\0\
+\0\0\0\x18\0\x1c\xb7\x02\0\0\0\0\0\0\x7b\x8a\x20\xff\0\0\0\0\x7b\x2a\x28\xff\0\
+\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\xf8\xff\xff\xff\x79\xa1\x38\xff\0\0\0\0\
+\x79\xa2\x40\xff\0\0\0\0\xb7\x04\0\0\x02\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\
+\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\
+\x01\xc8\0\0\0\0\0\xbf\x91\0\0\0\0\0\0\x15\x01\x26\0\x3c\0\0\0\x15\x01\x5f\0\
+\x2c\0\0\0\x55\x01\x60\0\x2b\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xf0\xff\0\0\0\0\
+\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\xf0\xff\xff\xff\x79\xa7\x38\xff\0\0\0\0\xbf\
+\x71\0\0\0\0\0\0\x79\xa2\x40\xff\0\0\0\0\xb7\x04\0\0\x04\0\0\0\xb7\x05\0\0\x01\
+\0\0\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\
+\0\x20\0\0\0\x55\x01\x07\x01\0\0\0\0\x71\xa1\xf2\xff\0\0\0\0\x55\x01\x11\0\x02\
+\0\0\0\x71\xa1\xf1\xff\0\0\0\0\x55\x01\x0f\0\x02\0\0\0\x71\xa1\xf3\xff\0\0\0\0\
+\x55\x01\x0d\0\x01\0\0\0\x79\xa2\x40\xff\0\0\0\0\x07\x02\0\0\x08\0\0\0\xbf\x71\
+\0\0\0\0\0\0\x79\xa3\x18\xff\0\0\0\0\xb7\x04\0\0\x10\0\0\0\xb7\x05\0\0\x01\0\0\
+\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\
+\x20\0\0\0\x55\x01\xf6\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x55\xff\0\0\0\0\
+\x18\x07\0\0\x01\0\0\0\0\0\0\0\0\x18\0\x1c\x05\0\x3c\0\0\0\0\0\xb7\x08\0\0\x02\
+\0\0\0\xb7\x07\0\0\0\0\0\0\x6b\x7a\xf0\xff\0\0\0\0\x05\0\x13\0\0\0\0\0\x0f\x81\
+\0\0\0\0\0\0\xbf\x12\0\0\0\0\0\0\x07\x02\0\0\x01\0\0\0\x71\xa3\xf9\xff\0\0\0\0\
+\x67\x03\0\0\x03\0\0\0\x3d\x32\x09\0\0\0\0\0\xbf\x72\0\0\0\0\0\0\x07\x02\0\0\
+\x01\0\0\0\x67\x07\0\0\x20\0\0\0\xbf\x73\0\0\0\0\0\0\x77\x03\0\0\x20\0\0\0\xbf\
+\x27\0\0\0\0\0\0\xbf\x18\0\0\0\0\0\0\xb7\x01\0\0\x1d\0\0\0\x2d\x31\x04\0\0\0\0\
+\0\x79\xa8\x20\xff\0\0\0\0\x18\x07\0\0\x01\0\0\0\0\0\0\0\0\x18\0\x1c\x05\0\x25\
+\0\0\0\0\0\xbf\x89\0\0\0\0\0\0\x79\xa1\x40\xff\0\0\0\0\x0f\x19\0\0\0\0\0\0\xbf\
+\xa3\0\0\0\0\0\0\x07\x03\0\0\xf0\xff\xff\xff\x79\xa1\x38\xff\0\0\0\0\xbf\x92\0\
+\0\0\0\0\0\xb7\x04\0\0\x02\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\xbf\
+\x01\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\x79\0\0\0\
+\0\0\x71\xa2\xf0\xff\0\0\0\0\x55\x02\x0e\0\xc9\0\0\0\x07\x09\0\0\x02\0\0\0\x79\
+\xa1\x38\xff\0\0\0\0\xbf\x92\0\0\0\0\0\0\x79\xa3\x10\xff\0\0\0\0\xb7\x04\0\0\
+\x10\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\
+\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\x6c\0\0\0\0\0\xb7\x01\0\0\x01\
+\0\0\0\x73\x1a\x54\xff\0\0\0\0\x05\0\xde\xff\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\
+\x02\xcd\xff\0\0\0\0\x71\xa1\xf1\xff\0\0\0\0\x07\x01\0\0\x02\0\0\0\x05\0\xca\
+\xff\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x56\xff\0\0\0\0\x71\xa1\xf9\xff\0\0\
+\0\0\x67\x01\0\0\x03\0\0\0\x79\xa2\x40\xff\0\0\0\0\x0f\x12\0\0\0\0\0\0\x07\x02\
+\0\0\x08\0\0\0\x7b\x2a\x40\xff\0\0\0\0\x71\xa9\xf8\xff\0\0\0\0\x79\xa2\x28\xff\
+\0\0\0\0\x25\x09\x0c\0\x3c\0\0\0\xb7\x01\0\0\x01\0\0\0\x6f\x91\0\0\0\0\0\0\x5f\
+\x71\0\0\0\0\0\0\x55\x01\x01\0\0\0\0\0\x05\0\x07\0\0\0\0\0\x07\x02\0\0\x01\0\0\
+\0\xbf\x21\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\x7d\
+\xff\x0b\0\0\0\x71\xa7\x56\xff\0\0\0\0\x05\0\x09\xff\0\0\0\0\x15\x09\xf8\xff\
+\x87\0\0\0\x05\0\xfc\xff\0\0\0\0\x71\xa1\x51\xff\0\0\0\0\x79\xa0\x30\xff\0\0\0\
+\0\x15\x01\x0e\x01\0\0\0\0\x71\x62\x03\0\0\0\0\0\x67\x02\0\0\x08\0\0\0\x71\x61\
+\x02\0\0\0\0\0\x4f\x12\0\0\0\0\0\0\x71\x63\x04\0\0\0\0\0\x67\x03\0\0\x10\0\0\0\
+\x71\x61\x05\0\0\0\0\0\x67\x01\0\0\x18\0\0\0\x4f\x31\0\0\0\0\0\0\x4f\x21\0\0\0\
+\0\0\0\x71\xa2\x53\xff\0\0\0\0\x15\x02\x42\0\0\0\0\0\xbf\x12\0\0\0\0\0\0\x57\
 \x02\0\0\x10\0\0\0\x15\x02\x3f\0\0\0\0\0\x57\x01\0\0\x80\0\0\0\xb7\x02\0\0\x10\
 \0\0\0\xb7\x03\0\0\x10\0\0\0\x15\x01\x01\0\0\0\0\0\xb7\x03\0\0\x30\0\0\0\x71\
-\xa4\x5d\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\x32\0\0\0\0\0\0\xbf\xa3\0\0\0\0\
-\0\0\x07\x03\0\0\x64\xff\xff\xff\xbf\x34\0\0\0\0\0\0\x15\x01\x02\0\0\0\0\0\xbf\
-\xa4\0\0\0\0\0\0\x07\x04\0\0\x84\xff\xff\xff\x71\xa5\x5c\xff\0\0\0\0\xbf\x31\0\
+\xa4\x55\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\x32\0\0\0\0\0\0\xbf\xa3\0\0\0\0\
+\0\0\x07\x03\0\0\x5c\xff\xff\xff\xbf\x34\0\0\0\0\0\0\x15\x01\x02\0\0\0\0\0\xbf\
+\xa4\0\0\0\0\0\0\x07\x04\0\0\x7c\xff\xff\xff\x71\xa5\x54\xff\0\0\0\0\xbf\x31\0\
 \0\0\0\0\0\x15\x05\x01\0\0\0\0\0\xbf\x41\0\0\0\0\0\0\x61\x14\x04\0\0\0\0\0\x67\
-\x04\0\0\x20\0\0\0\x61\x15\0\0\0\0\0\0\x4f\x54\0\0\0\0\0\0\x7b\x4a\xa8\xff\0\0\
+\x04\0\0\x20\0\0\0\x61\x15\0\0\0\0\0\0\x4f\x54\0\0\0\0\0\0\x7b\x4a\xa0\xff\0\0\
 \0\0\x61\x14\x08\0\0\0\0\0\x61\x11\x0c\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x4f\x41\
-\0\0\0\0\0\0\x7b\x1a\xb0\xff\0\0\0\0\x0f\x23\0\0\0\0\0\0\x61\x31\0\0\0\0\0\0\
-\x61\x32\x04\0\0\0\0\0\x61\x34\x08\0\0\0\0\0\x61\x33\x0c\0\0\0\0\0\x69\xa5\x62\
-\xff\0\0\0\0\x6b\x5a\xca\xff\0\0\0\0\x69\xa5\x60\xff\0\0\0\0\x6b\x5a\xc8\xff\0\
-\0\0\0\x67\x03\0\0\x20\0\0\0\x4f\x43\0\0\0\0\0\0\x7b\x3a\xc0\xff\0\0\0\0\x67\
-\x02\0\0\x20\0\0\0\x4f\x12\0\0\0\0\0\0\x7b\x2a\xb8\xff\0\0\0\0\x05\0\x6b\0\0\0\
-\0\0\x71\xa2\x5a\xff\0\0\0\0\x15\x02\x04\0\0\0\0\0\xbf\x12\0\0\0\0\0\0\x57\x02\
+\0\0\0\0\0\0\x7b\x1a\xa8\xff\0\0\0\0\x0f\x23\0\0\0\0\0\0\x61\x31\0\0\0\0\0\0\
+\x61\x32\x04\0\0\0\0\0\x61\x34\x08\0\0\0\0\0\x61\x33\x0c\0\0\0\0\0\x69\xa5\x5a\
+\xff\0\0\0\0\x6b\x5a\xc2\xff\0\0\0\0\x69\xa5\x58\xff\0\0\0\0\x6b\x5a\xc0\xff\0\
+\0\0\0\x67\x03\0\0\x20\0\0\0\x4f\x43\0\0\0\0\0\0\x7b\x3a\xb8\xff\0\0\0\0\x67\
+\x02\0\0\x20\0\0\0\x4f\x12\0\0\0\0\0\0\x7b\x2a\xb0\xff\0\0\0\0\x05\0\x6a\0\0\0\
+\0\0\x71\xa2\x52\xff\0\0\0\0\x15\x02\x04\0\0\0\0\0\xbf\x12\0\0\0\0\0\0\x57\x02\
 \0\0\x04\0\0\0\x15\x02\x01\0\0\0\0\0\x05\0\xf1\xfe\0\0\0\0\x57\x01\0\0\x01\0\0\
-\0\x15\x01\xd0\0\0\0\0\0\x61\xa1\x64\xff\0\0\0\0\x63\x1a\xa8\xff\0\0\0\0\x61\
-\xa1\x68\xff\0\0\0\0\x63\x1a\xac\xff\0\0\0\0\x05\0\x5e\0\0\0\0\0\xb7\x09\0\0\
-\x3c\0\0\0\x79\xa8\x28\xff\0\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x15\
-\0\xac\xff\0\0\0\0\x05\0\xc5\0\0\0\0\0\x71\xa2\x5a\xff\0\0\0\0\x15\x02\x26\0\0\
+\0\x15\x01\xcb\0\0\0\0\0\x61\xa1\x5c\xff\0\0\0\0\x63\x1a\xa0\xff\0\0\0\0\x61\
+\xa1\x60\xff\0\0\0\0\x63\x1a\xa4\xff\0\0\0\0\x05\0\x5d\0\0\0\0\0\xb7\x09\0\0\
+\x3c\0\0\0\x79\xa8\x20\xff\0\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x15\
+\0\xac\xff\0\0\0\0\x05\0\xc0\0\0\0\0\0\x71\xa2\x52\xff\0\0\0\0\x15\x02\x26\0\0\
 \0\0\0\xbf\x12\0\0\0\0\0\0\x57\x02\0\0\x20\0\0\0\x15\x02\x23\0\0\0\0\0\x57\x01\
 \0\0\0\x01\0\0\xb7\x02\0\0\x10\0\0\0\xb7\x03\0\0\x10\0\0\0\x15\x01\x01\0\0\0\0\
-\0\xb7\x03\0\0\x30\0\0\0\x71\xa4\x5d\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\x32\
-\0\0\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\x64\xff\xff\xff\xbf\x34\0\0\0\0\0\
-\0\x15\x01\x02\0\0\0\0\0\xbf\xa4\0\0\0\0\0\0\x07\x04\0\0\x84\xff\xff\xff\x71\
-\xa5\x5c\xff\0\0\0\0\xbf\x31\0\0\0\0\0\0\x15\x05\xbd\xff\0\0\0\0\x05\0\xbb\xff\
-\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x5a\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x7b\
-\x1a\xd0\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\xd0\xff\xff\xff\x79\xa1\
-\x40\xff\0\0\0\0\x79\xa2\x48\xff\0\0\0\0\xb7\x04\0\0\x08\0\0\0\xb7\x05\0\0\x01\
-\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x55\0\xa0\0\
+\0\xb7\x03\0\0\x30\0\0\0\x71\xa4\x55\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\x32\
+\0\0\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\x5c\xff\xff\xff\xbf\x34\0\0\0\0\0\
+\0\x15\x01\x02\0\0\0\0\0\xbf\xa4\0\0\0\0\0\0\x07\x04\0\0\x7c\xff\xff\xff\x71\
+\xa5\x54\xff\0\0\0\0\xbf\x31\0\0\0\0\0\0\x15\x05\xbd\xff\0\0\0\0\x05\0\xbb\xff\
+\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x52\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x7b\
+\x1a\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\xc8\xff\xff\xff\x79\xa1\
+\x38\xff\0\0\0\0\x79\xa2\x40\xff\0\0\0\0\xb7\x04\0\0\x08\0\0\0\xb7\x05\0\0\x01\
+\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x55\0\x9b\0\
 \0\0\0\0\x05\0\xa8\xfe\0\0\0\0\x15\x09\xf3\xfe\x87\0\0\0\x05\0\x83\xff\0\0\0\0\
-\xbf\x12\0\0\0\0\0\0\x57\x02\0\0\x08\0\0\0\x15\x02\x9a\0\0\0\0\0\x57\x01\0\0\
+\xbf\x12\0\0\0\0\0\0\x57\x02\0\0\x08\0\0\0\x15\x02\x95\0\0\0\0\0\x57\x01\0\0\
 \x40\0\0\0\xb7\x02\0\0\x0c\0\0\0\xb7\x03\0\0\x0c\0\0\0\x15\x01\x01\0\0\0\0\0\
-\xb7\x03\0\0\x2c\0\0\0\x71\xa4\x5c\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\x32\0\
-\0\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\x58\xff\xff\xff\x0f\x23\0\0\0\0\0\0\
+\xb7\x03\0\0\x2c\0\0\0\x71\xa4\x54\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\x32\0\
+\0\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\x50\xff\xff\xff\x0f\x23\0\0\0\0\0\0\
 \x61\x32\x04\0\0\0\0\0\x67\x02\0\0\x20\0\0\0\x61\x34\0\0\0\0\0\0\x4f\x42\0\0\0\
-\0\0\0\x7b\x2a\xa8\xff\0\0\0\0\x61\x32\x08\0\0\0\0\0\x61\x33\x0c\0\0\0\0\0\x67\
-\x03\0\0\x20\0\0\0\x4f\x23\0\0\0\0\0\0\x7b\x3a\xb0\xff\0\0\0\0\x71\xa2\x5d\xff\
-\0\0\0\0\x15\x02\x0c\0\0\0\0\0\x15\x01\x0b\0\0\0\0\0\x61\xa1\xa0\xff\0\0\0\0\
-\x67\x01\0\0\x20\0\0\0\x61\xa2\x9c\xff\0\0\0\0\x4f\x21\0\0\0\0\0\0\x7b\x1a\xc0\
-\xff\0\0\0\0\x61\xa1\x98\xff\0\0\0\0\x67\x01\0\0\x20\0\0\0\x61\xa2\x94\xff\0\0\
-\0\0\x05\0\x0a\0\0\0\0\0\xb7\x09\0\0\x2b\0\0\0\x05\0\xae\xff\0\0\0\0\x61\xa1\
-\x80\xff\0\0\0\0\x67\x01\0\0\x20\0\0\0\x61\xa2\x7c\xff\0\0\0\0\x4f\x21\0\0\0\0\
-\0\0\x7b\x1a\xc0\xff\0\0\0\0\x61\xa1\x78\xff\0\0\0\0\x67\x01\0\0\x20\0\0\0\x61\
-\xa2\x74\xff\0\0\0\0\x4f\x21\0\0\0\0\0\0\x7b\x1a\xb8\xff\0\0\0\0\xb7\x02\0\0\0\
-\0\0\0\x07\x08\0\0\x04\0\0\0\x61\x03\0\0\0\0\0\0\xb7\x05\0\0\0\0\0\0\xbf\xa1\0\
-\0\0\0\0\0\x07\x01\0\0\xa8\xff\xff\xff\x0f\x21\0\0\0\0\0\0\x71\x14\0\0\0\0\0\0\
-\xbf\x41\0\0\0\0\0\0\x67\x01\0\0\x38\0\0\0\xc7\x01\0\0\x3f\0\0\0\x5f\x31\0\0\0\
-\0\0\0\xaf\x51\0\0\0\0\0\0\xbf\x85\0\0\0\0\0\0\x0f\x25\0\0\0\0\0\0\x71\x55\0\0\
-\0\0\0\0\x67\x03\0\0\x01\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x07\0\0\0\x4f\x03\
-\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x39\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\
-\x30\0\0\0\0\0\0\xaf\x01\0\0\0\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x06\0\0\0\
-\x57\0\0\0\x01\0\0\0\x67\x03\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\
-\0\0\x67\0\0\0\x3a\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x01\0\0\0\
-\0\0\0\x67\x03\0\0\x01\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x05\0\0\0\x57\0\0\0\
-\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3b\0\0\0\xc7\0\0\
-\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x01\0\0\0\0\0\0\x67\x03\0\0\x01\0\0\0\xbf\
-\x50\0\0\0\0\0\0\x77\0\0\0\x04\0\0\0\x57\0\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\
-\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3c\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\
-\0\xaf\x01\0\0\0\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x03\0\0\0\x57\0\0\0\x01\0\
-\0\0\x67\x03\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\
-\x3d\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x01\0\0\0\0\0\0\xbf\x50\
-\0\0\0\0\0\0\x77\0\0\0\x02\0\0\0\x57\0\0\0\x01\0\0\0\x67\x03\0\0\x01\0\0\0\x4f\
-\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3e\0\0\0\xc7\0\0\0\x3f\0\0\0\
-\x5f\x30\0\0\0\0\0\0\xaf\x01\0\0\0\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x01\0\0\
-\0\x57\0\0\0\x01\0\0\0\x67\x03\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\x57\x04\0\0\
-\x01\0\0\0\x87\x04\0\0\0\0\0\0\x5f\x34\0\0\0\0\0\0\xaf\x41\0\0\0\0\0\0\x57\x05\
-\0\0\x01\0\0\0\x67\x03\0\0\x01\0\0\0\x4f\x53\0\0\0\0\0\0\x07\x02\0\0\x01\0\0\0\
-\xbf\x15\0\0\0\0\0\0\x15\x02\x01\0\x24\0\0\0\x05\0\xa9\xff\0\0\0\0\xbf\x12\0\0\
-\0\0\0\0\x67\x02\0\0\x20\0\0\0\x77\x02\0\0\x20\0\0\0\x15\x02\x0e\0\0\0\0\0\x71\
-\x63\x06\0\0\0\0\0\x71\x64\x07\0\0\0\0\0\x67\x04\0\0\x08\0\0\0\x4f\x34\0\0\0\0\
-\0\0\x3f\x42\0\0\0\0\0\0\x2f\x42\0\0\0\0\0\0\x1f\x21\0\0\0\0\0\0\x63\x1a\x58\
-\xff\0\0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\x58\xff\xff\xff\x18\x01\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\x55\0\x05\0\0\0\0\0\x71\x61\x08\0\0\0\0\
-\0\x71\x60\x09\0\0\0\0\0\x67\0\0\0\x08\0\0\0\x4f\x10\0\0\0\0\0\0\x95\0\0\0\0\0\
-\0\0\x69\0\0\0\0\0\0\0\x05\0\xfd\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\x7b\x2a\xa0\xff\0\0\0\0\x61\x32\x08\0\0\0\0\0\x61\x33\x0c\0\0\0\0\0\x67\
+\x03\0\0\x20\0\0\0\x4f\x23\0\0\0\0\0\0\x7b\x3a\xa8\xff\0\0\0\0\xbf\xa2\0\0\0\0\
+\0\0\x07\x02\0\0\xb0\xff\xff\xff\x71\xa3\x55\xff\0\0\0\0\x15\x03\x0b\0\0\0\0\0\
+\x15\x01\x0a\0\0\0\0\0\x61\xa1\x98\xff\0\0\0\0\x63\x12\x0c\0\0\0\0\0\x61\xa1\
+\x94\xff\0\0\0\0\x63\x12\x08\0\0\0\0\0\x61\xa1\x90\xff\0\0\0\0\x63\x12\x04\0\0\
+\0\0\0\x61\xa1\x8c\xff\0\0\0\0\x05\0\x09\0\0\0\0\0\xb7\x09\0\0\x2b\0\0\0\x05\0\
+\xad\xff\0\0\0\0\x61\xa1\x78\xff\0\0\0\0\x63\x12\x0c\0\0\0\0\0\x61\xa1\x74\xff\
+\0\0\0\0\x63\x12\x08\0\0\0\0\0\x61\xa1\x70\xff\0\0\0\0\x63\x12\x04\0\0\0\0\0\
+\x61\xa1\x6c\xff\0\0\0\0\x63\x12\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x07\x08\0\0\
+\x04\0\0\0\x61\x03\0\0\0\0\0\0\xb7\x05\0\0\0\0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\
+\0\0\xa0\xff\xff\xff\x0f\x12\0\0\0\0\0\0\x71\x24\0\0\0\0\0\0\xbf\x42\0\0\0\0\0\
+\0\x67\x02\0\0\x38\0\0\0\xc7\x02\0\0\x3f\0\0\0\x5f\x32\0\0\0\0\0\0\xaf\x52\0\0\
+\0\0\0\0\xbf\x85\0\0\0\0\0\0\x0f\x15\0\0\0\0\0\0\x71\x55\0\0\0\0\0\0\x67\x03\0\
+\0\x01\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x07\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\
+\x40\0\0\0\0\0\0\x67\0\0\0\x39\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\
+\xaf\x02\0\0\0\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x06\0\0\0\x57\0\0\0\x01\0\0\
+\0\x67\x03\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3a\
+\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\0\0\x67\x03\0\0\
+\x01\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x05\0\0\0\x57\0\0\0\x01\0\0\0\x4f\x03\
+\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3b\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\
+\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\0\0\x67\x03\0\0\x01\0\0\0\xbf\x50\0\0\0\0\0\0\
+\x77\0\0\0\x04\0\0\0\x57\0\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\
+\0\x67\0\0\0\x3c\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\
+\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x03\0\0\0\x57\0\0\0\x01\0\0\0\x67\x03\0\0\
+\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3d\0\0\0\xc7\0\0\
+\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\
+\0\0\x02\0\0\0\x57\0\0\0\x01\0\0\0\x67\x03\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\
+\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3e\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\
+\0\xaf\x02\0\0\0\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x01\0\0\0\x57\0\0\0\x01\0\
+\0\0\x67\x03\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\x57\x04\0\0\x01\0\0\0\x87\x04\0\
+\0\0\0\0\0\x5f\x34\0\0\0\0\0\0\xaf\x42\0\0\0\0\0\0\x57\x05\0\0\x01\0\0\0\x67\
+\x03\0\0\x01\0\0\0\x4f\x53\0\0\0\0\0\0\x07\x01\0\0\x01\0\0\0\xbf\x25\0\0\0\0\0\
+\0\x15\x01\x01\0\x24\0\0\0\x05\0\xa9\xff\0\0\0\0\x71\x61\x06\0\0\0\0\0\x71\x63\
+\x07\0\0\0\0\0\x67\x03\0\0\x08\0\0\0\x4f\x13\0\0\0\0\0\0\x67\x02\0\0\x20\0\0\0\
+\x77\x02\0\0\x20\0\0\0\x9f\x32\0\0\0\0\0\0\x63\x2a\x50\xff\0\0\0\0\xbf\xa2\0\0\
+\0\0\0\0\x07\x02\0\0\x50\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x85\0\
+\0\0\x01\0\0\0\x55\0\x05\0\0\0\0\0\x71\x61\x08\0\0\0\0\0\x71\x60\x09\0\0\0\0\0\
+\x67\0\0\0\x08\0\0\0\x4f\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x69\0\0\0\0\0\0\0\
+\x05\0\xfd\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\x47\x50\x4c\x20\x76\x32\0\0\x9f\xeb\x01\0\x18\0\0\0\0\0\0\0\x10\x05\0\0\x10\
-\x05\0\0\x65\x11\0\0\0\0\0\0\0\0\0\x02\x03\0\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\
-\x20\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x02\0\0\0\x05\0\0\0\
-\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\x02\x06\0\0\0\0\0\0\0\0\0\0\x03\0\
-\0\0\0\x02\0\0\0\x04\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\x02\x08\0\0\0\0\0\0\0\0\0\0\
-\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x0a\0\0\0\0\0\0\0\0\0\0\x02\x0a\0\0\0\0\0\0\0\
-\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x01\0\0\0\0\0\0\0\x04\0\0\x04\x20\0\0\0\
-\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0\x27\0\0\0\x07\0\0\0\
-\x80\0\0\0\x32\0\0\0\x09\0\0\0\xc0\0\0\0\x3e\0\0\0\0\0\0\x0e\x0b\0\0\0\x01\0\0\
-\0\0\0\0\0\0\0\0\x02\x0e\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\
-\x28\0\0\0\0\0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\
-\x05\0\0\0\x40\0\0\0\x27\0\0\0\x0d\0\0\0\x80\0\0\0\x32\0\0\0\x09\0\0\0\xc0\0\0\
-\0\x59\0\0\0\0\0\0\x0e\x0f\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x12\0\0\0\0\0\0\0\
-\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x80\0\0\0\0\0\0\0\x04\0\0\x04\x20\0\0\0\
-\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0\x27\0\0\0\x01\0\0\0\
-\x80\0\0\0\x32\0\0\0\x11\0\0\0\xc0\0\0\0\x72\0\0\0\0\0\0\x0e\x13\0\0\0\x01\0\0\
-\0\0\0\0\0\0\0\0\x02\x16\0\0\0\x90\0\0\0\x22\0\0\x04\xc0\0\0\0\x9a\0\0\0\x17\0\
-\0\0\0\0\0\0\x9e\0\0\0\x17\0\0\0\x20\0\0\0\xa7\0\0\0\x17\0\0\0\x40\0\0\0\xac\0\
-\0\0\x17\0\0\0\x60\0\0\0\xba\0\0\0\x17\0\0\0\x80\0\0\0\xc3\0\0\0\x17\0\0\0\xa0\
-\0\0\0\xd0\0\0\0\x17\0\0\0\xc0\0\0\0\xd9\0\0\0\x17\0\0\0\xe0\0\0\0\xe4\0\0\0\
-\x17\0\0\0\0\x01\0\0\xed\0\0\0\x17\0\0\0\x20\x01\0\0\xfd\0\0\0\x17\0\0\0\x40\
-\x01\0\0\x05\x01\0\0\x17\0\0\0\x60\x01\0\0\x0e\x01\0\0\x19\0\0\0\x80\x01\0\0\
-\x11\x01\0\0\x17\0\0\0\x20\x02\0\0\x16\x01\0\0\x17\0\0\0\x40\x02\0\0\x21\x01\0\
-\0\x17\0\0\0\x60\x02\0\0\x26\x01\0\0\x17\0\0\0\x80\x02\0\0\x2f\x01\0\0\x17\0\0\
-\0\xa0\x02\0\0\x37\x01\0\0\x17\0\0\0\xc0\x02\0\0\x3e\x01\0\0\x17\0\0\0\xe0\x02\
-\0\0\x49\x01\0\0\x17\0\0\0\0\x03\0\0\x53\x01\0\0\x1a\0\0\0\x20\x03\0\0\x5e\x01\
-\0\0\x1a\0\0\0\xa0\x03\0\0\x68\x01\0\0\x17\0\0\0\x20\x04\0\0\x74\x01\0\0\x17\0\
-\0\0\x40\x04\0\0\x7f\x01\0\0\x17\0\0\0\x60\x04\0\0\0\0\0\0\x1b\0\0\0\x80\x04\0\
-\0\x89\x01\0\0\x1d\0\0\0\xc0\x04\0\0\x90\x01\0\0\x17\0\0\0\0\x05\0\0\x99\x01\0\
-\0\x17\0\0\0\x20\x05\0\0\0\0\0\0\x1f\0\0\0\x40\x05\0\0\xa2\x01\0\0\x17\0\0\0\
-\x80\x05\0\0\xab\x01\0\0\x21\0\0\0\xa0\x05\0\0\xb7\x01\0\0\x1d\0\0\0\xc0\x05\0\
-\0\xc0\x01\0\0\0\0\0\x08\x18\0\0\0\xc6\x01\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\
-\0\0\0\0\0\0\x03\0\0\0\0\x17\0\0\0\x04\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\
-\0\x17\0\0\0\x04\0\0\0\x04\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\xd3\x01\0\0\x1c\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x2a\0\0\0\xdd\x01\0\0\0\0\0\x08\x1e\0\0\0\xe3\
-\x01\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\xf6\x01\0\
-\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x2b\0\0\0\xf9\x01\0\0\0\0\0\x08\x22\0\0\
-\0\xfe\x01\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\x0c\
-\x02\0\0\x15\0\0\0\x10\x02\0\0\x01\0\0\x0c\x23\0\0\0\x32\x11\0\0\0\0\0\x01\x01\
-\0\0\0\x08\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x25\0\0\0\x04\0\0\0\x07\0\0\0\x37\
-\x11\0\0\0\0\0\x0e\x26\0\0\0\x01\0\0\0\x40\x11\0\0\x03\0\0\x0f\0\0\0\0\x0c\0\0\
-\0\0\0\0\0\x20\0\0\0\x10\0\0\0\0\0\0\0\x20\0\0\0\x14\0\0\0\0\0\0\0\x20\0\0\0\
-\x46\x11\0\0\x01\0\0\x0f\0\0\0\0\x27\0\0\0\0\0\0\0\x07\0\0\0\x4e\x11\0\0\0\0\0\
-\x07\0\0\0\0\x5c\x11\0\0\0\0\0\x07\0\0\0\0\0\x69\x6e\x74\0\x5f\x5f\x41\x52\x52\
-\x41\x59\x5f\x53\x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x74\x79\x70\x65\0\
-\x6b\x65\x79\x5f\x73\x69\x7a\x65\0\x76\x61\x6c\x75\x65\x5f\x73\x69\x7a\x65\0\
-\x6d\x61\x78\x5f\x65\x6e\x74\x72\x69\x65\x73\0\x74\x61\x70\x5f\x72\x73\x73\x5f\
-\x6d\x61\x70\x5f\x63\x6f\x6e\x66\x69\x67\x75\x72\x61\x74\x69\x6f\x6e\x73\0\x74\
-\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x74\x6f\x65\x70\x6c\x69\x74\x7a\
-\x5f\x6b\x65\x79\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x69\x6e\x64\
-\x69\x72\x65\x63\x74\x69\x6f\x6e\x5f\x74\x61\x62\x6c\x65\0\x5f\x5f\x73\x6b\x5f\
-\x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\x79\x70\x65\0\x6d\x61\x72\
-\x6b\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x70\x72\x6f\x74\
-\x6f\x63\x6f\x6c\0\x76\x6c\x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\x74\0\x76\x6c\
-\x61\x6e\x5f\x74\x63\x69\0\x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\x6f\0\x70\x72\
-\x69\x6f\x72\x69\x74\x79\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\x66\x69\x6e\x64\
-\x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\x64\x65\x78\0\x63\
-\x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\x64\0\x64\x61\x74\
-\x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\x69\x64\0\x66\x61\
-\x6d\x69\x6c\x79\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\x6c\x6f\x63\x61\
-\x6c\x5f\x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\0\x6c\x6f\x63\
-\x61\x6c\x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\0\x6c\
-\x6f\x63\x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\0\
-\x74\x73\x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\x73\x6f\x5f\
-\x73\x65\x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x74\x73\x74\x61\x6d\x70\
-\x5f\x74\x79\x70\x65\0\x68\x77\x74\x73\x74\x61\x6d\x70\0\x5f\x5f\x75\x33\x32\0\
-\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x66\x6c\x6f\x77\x5f\x6b\x65\
-\x79\x73\0\x5f\x5f\x75\x36\x34\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\
-\x6e\x67\x20\x6c\x6f\x6e\x67\0\x73\x6b\0\x5f\x5f\x75\x38\0\x75\x6e\x73\x69\x67\
-\x6e\x65\x64\x20\x63\x68\x61\x72\0\x73\x6b\x62\0\x74\x75\x6e\x5f\x72\x73\x73\
-\x5f\x73\x74\x65\x65\x72\x69\x6e\x67\x5f\x70\x72\x6f\x67\0\x74\x75\x6e\x5f\x72\
-\x73\x73\x5f\x73\x74\x65\x65\x72\x69\x6e\x67\0\x2f\x68\x6f\x6d\x65\x2f\x73\x68\
-\x72\x65\x65\x73\x68\x2f\x63\x2f\x71\x65\x6d\x75\x2f\x74\x6f\x6f\x6c\x73\x2f\
-\x65\x62\x70\x66\x2f\x72\x73\x73\x2e\x62\x70\x66\x2e\x63\0\x69\x6e\x74\x20\x74\
-\x75\x6e\x5f\x72\x73\x73\x5f\x73\x74\x65\x65\x72\x69\x6e\x67\x5f\x70\x72\x6f\
-\x67\x28\x73\x74\x72\x75\x63\x74\x20\x5f\x5f\x73\x6b\x5f\x62\x75\x66\x66\x20\
-\x2a\x73\x6b\x62\x29\0\x20\x20\x20\x20\x5f\x5f\x75\x33\x32\x20\x6b\x65\x79\x20\
-\x3d\x20\x30\x3b\0\x20\x20\x20\x20\x63\x6f\x6e\x66\x69\x67\x20\x3d\x20\x62\x70\
-\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\
-\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x63\x6f\x6e\x66\x69\x67\x75\
-\x72\x61\x74\x69\x6f\x6e\x73\x2c\x20\x26\x6b\x65\x79\x29\x3b\0\x20\x20\x20\x20\
-\x74\x6f\x65\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\
-\x70\x5f\x65\x6c\x65\x6d\x28\x26\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\
-\x5f\x74\x6f\x65\x70\x6c\x69\x74\x7a\x5f\x6b\x65\x79\x2c\x20\x26\x6b\x65\x79\
-\x29\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\x63\x6f\x6e\x66\x69\x67\x20\x26\x26\
-\x20\x74\x6f\x65\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\
-\x21\x63\x6f\x6e\x66\x69\x67\x2d\x3e\x72\x65\x64\x69\x72\x65\x63\x74\x29\x20\
-\x7b\0\x20\x20\x20\x20\x5f\x5f\x75\x38\x20\x72\x73\x73\x5f\x69\x6e\x70\x75\x74\
-\x5b\x48\x41\x53\x48\x5f\x43\x41\x4c\x43\x55\x4c\x41\x54\x49\x4f\x4e\x5f\x42\
-\x55\x46\x46\x45\x52\x5f\x53\x49\x5a\x45\x5d\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\
-\x20\x20\x73\x74\x72\x75\x63\x74\x20\x70\x61\x63\x6b\x65\x74\x5f\x68\x61\x73\
-\x68\x5f\x69\x6e\x66\x6f\x5f\x74\x20\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\
-\x6f\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\x21\x69\x6e\x66\
-\x6f\x20\x7c\x7c\x20\x21\x73\x6b\x62\x29\x20\x7b\0\x20\x20\x20\x20\x5f\x5f\x62\
-\x65\x31\x36\x20\x72\x65\x74\x20\x3d\x20\x30\x3b\0\x20\x20\x20\x20\x65\x72\x72\
-\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\
-\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x6f\x66\
-\x66\x73\x65\x74\x2c\x20\x26\x72\x65\x74\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\
-\x72\x65\x74\x29\x2c\0\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x29\x20\x7b\
-\0\x20\x20\x20\x20\x73\x77\x69\x74\x63\x68\x20\x28\x62\x70\x66\x5f\x6e\x74\x6f\
-\x68\x73\x28\x72\x65\x74\x29\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x65\
-\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\
-\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\
-\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x72\x65\x74\x2c\x20\x73\x69\x7a\x65\x6f\
-\x66\x28\x72\x65\x74\x29\x2c\0\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\
-\x65\x74\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\x6c\x33\x5f\x70\x72\x6f\x74\x6f\
-\x63\x6f\x6c\x20\x3d\x3d\x20\x30\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\
-\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x69\x70\x76\x34\x20\x3d\x20\x31\x3b\0\x20\
-\x20\x20\x20\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x69\x70\x68\x64\x72\
-\x20\x69\x70\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\
-\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\
-\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x30\
-\x2c\x20\x26\x69\x70\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\x69\x70\x29\x2c\0\x20\
-\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x29\x20\x7b\0\x20\x20\
-\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x66\x72\x61\x67\
-\x6d\x65\x6e\x74\x65\x64\x20\x3d\x20\x21\x21\x69\x70\x2e\x66\x72\x61\x67\x5f\
-\x6f\x66\x66\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\
-\x6e\x5f\x73\x72\x63\x20\x3d\x20\x69\x70\x2e\x73\x61\x64\x64\x72\x3b\0\x20\x20\
-\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x6e\x5f\x64\x73\x74\x20\
-\x3d\x20\x69\x70\x2e\x64\x61\x64\x64\x72\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\
-\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x20\x69\x70\x2e\x70\x72\
-\x6f\x74\x6f\x63\x6f\x6c\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x6c\x34\x5f\x6f\
-\x66\x66\x73\x65\x74\x20\x3d\x20\x69\x70\x2e\x69\x68\x6c\x20\x2a\x20\x34\x3b\0\
-\x20\x20\x20\x20\x69\x66\x20\x28\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\
-\x20\x21\x3d\x20\x30\x20\x26\x26\x20\x21\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\
-\x66\x72\x61\x67\x6d\x65\x6e\x74\x65\x64\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\
-\x20\x20\x69\x66\x20\x28\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\
-\x3d\x20\x49\x50\x50\x52\x4f\x54\x4f\x5f\x54\x43\x50\x29\x20\x7b\0\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x74\
-\x63\x70\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x73\x74\x72\x75\x63\x74\x20\x74\x63\x70\x68\x64\x72\x20\x74\x63\x70\x20\x3d\
-\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\
-\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\
-\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x6c\x34\
-\x5f\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x74\x63\x70\x2c\x20\x73\x69\x7a\x65\
-\x6f\x66\x28\x74\x63\x70\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x69\x66\x20\x28\x65\x72\x72\x29\x20\x7b\0\x20\x20\x20\x20\x69\x66\x20\x28\
-\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\x69\x70\x76\x34\
-\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x70\x61\x63\x6b\
-\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\x74\x63\x70\x20\x26\x26\0\x20\x20\
-\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x69\x70\x76\x36\
-\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\
-\x20\x69\x70\x76\x36\x68\x64\x72\x20\x69\x70\x36\x20\x3d\x20\x7b\x7d\x3b\0\x20\
-\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\
-\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\
-\x76\x65\x28\x73\x6b\x62\x2c\x20\x30\x2c\x20\x26\x69\x70\x36\x2c\x20\x73\x69\
-\x7a\x65\x6f\x66\x28\x69\x70\x36\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\
-\x6e\x66\x6f\x2d\x3e\x69\x6e\x36\x5f\x73\x72\x63\x20\x3d\x20\x69\x70\x36\x2e\
-\x73\x61\x64\x64\x72\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\
-\x3e\x69\x6e\x36\x5f\x64\x73\x74\x20\x3d\x20\x69\x70\x36\x2e\x64\x61\x64\x64\
-\x72\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\
-\x6f\x6c\x20\x3d\x20\x69\x70\x36\x2e\x6e\x65\x78\x74\x68\x64\x72\x3b\0\x20\x20\
-\x20\x20\x73\x77\x69\x74\x63\x68\x20\x28\x68\x64\x72\x5f\x74\x79\x70\x65\x29\
-\x20\x7b\0\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x69\x70\x76\x36\x5f\x6f\
-\x70\x74\x5f\x68\x64\x72\x20\x65\x78\x74\x5f\x68\x64\x72\x20\x3d\x20\x7b\x7d\
-\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\
-\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\
-\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\
-\x74\x2c\x20\x26\x65\x78\x74\x5f\x68\x64\x72\x2c\0\x20\x20\x20\x20\x20\x20\x20\
-\x20\x69\x66\x20\x28\x2a\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\
-\x3d\x20\x49\x50\x50\x52\x4f\x54\x4f\x5f\x52\x4f\x55\x54\x49\x4e\x47\x29\x20\
-\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\
-\x20\x69\x70\x76\x36\x5f\x72\x74\x5f\x68\x64\x72\x20\x65\x78\x74\x5f\x72\x74\
-\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x65\
-\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\
-\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\
-\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x65\x78\x74\x5f\x72\x74\
-\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x28\x65\
-\x78\x74\x5f\x72\x74\x2e\x74\x79\x70\x65\x20\x3d\x3d\x20\x49\x50\x56\x36\x5f\
-\x53\x52\x43\x52\x54\x5f\x54\x59\x50\x45\x5f\x32\x29\x20\x26\x26\0\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2a\x6c\
-\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x20\x6f\x66\x66\x73\x65\x74\x6f\x66\
-\x28\x73\x74\x72\x75\x63\x74\x20\x72\x74\x32\x5f\x68\x64\x72\x2c\x20\x61\x64\
-\x64\x72\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x47\x50\x4c\x20\x76\
+\x32\0\0\x9f\xeb\x01\0\x18\0\0\0\0\0\0\0\x50\x05\0\0\x50\x05\0\0\x8e\x11\0\0\0\
+\0\0\0\0\0\0\x02\x03\0\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\0\
+\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x02\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\
+\x20\0\0\0\0\0\0\0\0\0\0\x02\x06\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\
+\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\x02\x08\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\
+\0\x04\0\0\0\x0a\0\0\0\0\0\0\0\0\0\0\x02\x0a\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\
+\x02\0\0\0\x04\0\0\0\x01\0\0\0\0\0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\0\0\x01\0\0\
+\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0\x27\0\0\0\x07\0\0\0\x80\0\0\0\x32\0\0\
+\0\x09\0\0\0\xc0\0\0\0\x3e\0\0\0\0\0\0\x0e\x0b\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\
+\x02\x0e\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x28\0\0\0\0\0\0\0\
+\x04\0\0\x04\x20\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\
+\0\x27\0\0\0\x0d\0\0\0\x80\0\0\0\x32\0\0\0\x09\0\0\0\xc0\0\0\0\x59\0\0\0\0\0\0\
+\x0e\x0f\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x12\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\
+\x02\0\0\0\x04\0\0\0\x80\0\0\0\0\0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\0\0\x01\0\0\
+\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0\x27\0\0\0\x01\0\0\0\x80\0\0\0\x32\0\0\
+\0\x11\0\0\0\xc0\0\0\0\x72\0\0\0\0\0\0\x0e\x13\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\
+\x02\x16\0\0\0\x90\0\0\0\x25\0\0\x04\xc8\0\0\0\x9a\0\0\0\x17\0\0\0\0\0\0\0\x9e\
+\0\0\0\x17\0\0\0\x20\0\0\0\xa7\0\0\0\x17\0\0\0\x40\0\0\0\xac\0\0\0\x17\0\0\0\
+\x60\0\0\0\xba\0\0\0\x17\0\0\0\x80\0\0\0\xc3\0\0\0\x17\0\0\0\xa0\0\0\0\xd0\0\0\
+\0\x17\0\0\0\xc0\0\0\0\xd9\0\0\0\x17\0\0\0\xe0\0\0\0\xe4\0\0\0\x17\0\0\0\0\x01\
+\0\0\xed\0\0\0\x17\0\0\0\x20\x01\0\0\xfd\0\0\0\x17\0\0\0\x40\x01\0\0\x05\x01\0\
+\0\x17\0\0\0\x60\x01\0\0\x0e\x01\0\0\x19\0\0\0\x80\x01\0\0\x11\x01\0\0\x17\0\0\
+\0\x20\x02\0\0\x16\x01\0\0\x17\0\0\0\x40\x02\0\0\x21\x01\0\0\x17\0\0\0\x60\x02\
+\0\0\x26\x01\0\0\x17\0\0\0\x80\x02\0\0\x2f\x01\0\0\x17\0\0\0\xa0\x02\0\0\x37\
+\x01\0\0\x17\0\0\0\xc0\x02\0\0\x3e\x01\0\0\x17\0\0\0\xe0\x02\0\0\x49\x01\0\0\
+\x17\0\0\0\0\x03\0\0\x53\x01\0\0\x1a\0\0\0\x20\x03\0\0\x5e\x01\0\0\x1a\0\0\0\
+\xa0\x03\0\0\x68\x01\0\0\x17\0\0\0\x20\x04\0\0\x74\x01\0\0\x17\0\0\0\x40\x04\0\
+\0\x7f\x01\0\0\x17\0\0\0\x60\x04\0\0\0\0\0\0\x1b\0\0\0\x80\x04\0\0\x89\x01\0\0\
+\x1d\0\0\0\xc0\x04\0\0\x90\x01\0\0\x17\0\0\0\0\x05\0\0\x99\x01\0\0\x17\0\0\0\
+\x20\x05\0\0\0\0\0\0\x1f\0\0\0\x40\x05\0\0\xa2\x01\0\0\x17\0\0\0\x80\x05\0\0\
+\xab\x01\0\0\x21\0\0\0\xa0\x05\0\0\xb7\x01\0\0\x1d\0\0\0\xc0\x05\0\0\xc0\x01\0\
+\0\x17\0\0\0\0\x06\0\0\xd0\x01\0\0\x23\0\0\0\x20\x06\0\0\xe1\x01\0\0\x23\0\0\0\
+\x30\x06\0\0\xf0\x01\0\0\0\0\0\x08\x18\0\0\0\xf6\x01\0\0\0\0\0\x01\x04\0\0\0\
+\x20\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x17\0\0\0\x04\0\0\0\x05\0\0\0\0\0\0\0\0\0\
+\0\x03\0\0\0\0\x17\0\0\0\x04\0\0\0\x04\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\x03\
+\x02\0\0\x1c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x2c\0\0\0\x0d\x02\0\0\0\0\0\x08\
+\x1e\0\0\0\x13\x02\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\
+\0\0\x26\x02\0\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x2d\0\0\0\x29\x02\0\0\0\0\
+\0\x08\x22\0\0\0\x2e\x02\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\0\x3c\x02\0\0\0\0\0\
+\x08\x24\0\0\0\x42\x02\0\0\0\0\0\x01\x02\0\0\0\x10\0\0\0\0\0\0\0\x01\0\0\x0d\
+\x02\0\0\0\x51\x02\0\0\x15\0\0\0\x55\x02\0\0\x01\0\0\x0c\x25\0\0\0\x5b\x11\0\0\
+\0\0\0\x01\x01\0\0\0\x08\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x27\0\0\0\x04\0\0\0\
+\x07\0\0\0\x60\x11\0\0\0\0\0\x0e\x28\0\0\0\x01\0\0\0\x69\x11\0\0\x03\0\0\x0f\0\
+\0\0\0\x0c\0\0\0\0\0\0\0\x20\0\0\0\x10\0\0\0\0\0\0\0\x20\0\0\0\x14\0\0\0\0\0\0\
+\0\x20\0\0\0\x6f\x11\0\0\x01\0\0\x0f\0\0\0\0\x29\0\0\0\0\0\0\0\x07\0\0\0\x77\
+\x11\0\0\0\0\0\x07\0\0\0\0\x85\x11\0\0\0\0\0\x07\0\0\0\0\0\x69\x6e\x74\0\x5f\
+\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x74\
+\x79\x70\x65\0\x6b\x65\x79\x5f\x73\x69\x7a\x65\0\x76\x61\x6c\x75\x65\x5f\x73\
+\x69\x7a\x65\0\x6d\x61\x78\x5f\x65\x6e\x74\x72\x69\x65\x73\0\x74\x61\x70\x5f\
+\x72\x73\x73\x5f\x6d\x61\x70\x5f\x63\x6f\x6e\x66\x69\x67\x75\x72\x61\x74\x69\
+\x6f\x6e\x73\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x74\x6f\x65\x70\
+\x6c\x69\x74\x7a\x5f\x6b\x65\x79\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\
+\x5f\x69\x6e\x64\x69\x72\x65\x63\x74\x69\x6f\x6e\x5f\x74\x61\x62\x6c\x65\0\x5f\
+\x5f\x73\x6b\x5f\x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\x79\x70\
+\x65\0\x6d\x61\x72\x6b\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\
+\x70\x72\x6f\x74\x6f\x63\x6f\x6c\0\x76\x6c\x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\
+\x74\0\x76\x6c\x61\x6e\x5f\x74\x63\x69\0\x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\
+\x6f\0\x70\x72\x69\x6f\x72\x69\x74\x79\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\
+\x66\x69\x6e\x64\x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\
+\x64\x65\x78\0\x63\x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\
+\x64\0\x64\x61\x74\x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\
+\x69\x64\0\x66\x61\x6d\x69\x6c\x79\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\
+\x6c\x6f\x63\x61\x6c\x5f\x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\
+\0\x6c\x6f\x63\x61\x6c\x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\
+\x72\x74\0\x6c\x6f\x63\x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\
+\x65\x74\x61\0\x74\x73\x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\
+\x73\x6f\x5f\x73\x65\x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x74\x73\x74\
+\x61\x6d\x70\x5f\x74\x79\x70\x65\0\x68\x77\x74\x73\x74\x61\x6d\x70\0\x76\x6e\
+\x65\x74\x5f\x68\x61\x73\x68\x5f\x76\x61\x6c\x75\x65\0\x76\x6e\x65\x74\x5f\x68\
+\x61\x73\x68\x5f\x72\x65\x70\x6f\x72\x74\0\x76\x6e\x65\x74\x5f\x72\x73\x73\x5f\
+\x71\x75\x65\x75\x65\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\x6e\x65\x64\
+\x20\x69\x6e\x74\0\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x5f\x5f\x75\x36\x34\0\
+\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\0\x73\
+\x6b\0\x5f\x5f\x75\x38\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\
+\x5f\x5f\x75\x31\x36\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x73\x68\x6f\x72\x74\
+\0\x73\x6b\x62\0\x74\x75\x6e\x5f\x72\x73\x73\x5f\x73\x74\x65\x65\x72\x69\x6e\
+\x67\x5f\x70\x72\x6f\x67\0\x73\x6f\x63\x6b\x65\x74\0\x2f\x68\x6f\x6d\x65\x2f\
+\x61\x6c\x61\x72\x6d\x2f\x71\x2f\x76\x61\x72\x2f\x71\x65\x6d\x75\x2f\x74\x6f\
+\x6f\x6c\x73\x2f\x65\x62\x70\x66\x2f\x72\x73\x73\x2e\x62\x70\x66\x2e\x63\0\x69\
+\x6e\x74\x20\x74\x75\x6e\x5f\x72\x73\x73\x5f\x73\x74\x65\x65\x72\x69\x6e\x67\
+\x5f\x70\x72\x6f\x67\x28\x73\x74\x72\x75\x63\x74\x20\x5f\x5f\x73\x6b\x5f\x62\
+\x75\x66\x66\x20\x2a\x73\x6b\x62\x29\0\x20\x20\x20\x20\x5f\x5f\x75\x33\x32\x20\
+\x6b\x65\x79\x20\x3d\x20\x30\x3b\0\x20\x20\x20\x20\x63\x6f\x6e\x66\x69\x67\x20\
+\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\
+\x65\x6d\x28\x26\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x63\x6f\x6e\
+\x66\x69\x67\x75\x72\x61\x74\x69\x6f\x6e\x73\x2c\x20\x26\x6b\x65\x79\x29\x3b\0\
+\x20\x20\x20\x20\x74\x6f\x65\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\
+\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x74\x61\x70\x5f\x72\x73\x73\
+\x5f\x6d\x61\x70\x5f\x74\x6f\x65\x70\x6c\x69\x74\x7a\x5f\x6b\x65\x79\x2c\x20\
+\x26\x6b\x65\x79\x29\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\x63\x6f\x6e\x66\x69\
+\x67\x20\x26\x26\x20\x74\x6f\x65\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\
+\x69\x66\x20\x28\x21\x63\x6f\x6e\x66\x69\x67\x2d\x3e\x72\x65\x64\x69\x72\x65\
+\x63\x74\x29\x20\x7b\0\x20\x20\x20\x20\x5f\x5f\x75\x38\x20\x72\x73\x73\x5f\x69\
+\x6e\x70\x75\x74\x5b\x48\x41\x53\x48\x5f\x43\x41\x4c\x43\x55\x4c\x41\x54\x49\
+\x4f\x4e\x5f\x42\x55\x46\x46\x45\x52\x5f\x53\x49\x5a\x45\x5d\x20\x3d\x20\x7b\
+\x7d\x3b\0\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x70\x61\x63\x6b\x65\x74\
+\x5f\x68\x61\x73\x68\x5f\x69\x6e\x66\x6f\x5f\x74\x20\x70\x61\x63\x6b\x65\x74\
+\x5f\x69\x6e\x66\x6f\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\
+\x21\x69\x6e\x66\x6f\x20\x7c\x7c\x20\x21\x73\x6b\x62\x29\x20\x7b\0\x20\x20\x20\
+\x20\x5f\x5f\x62\x65\x31\x36\x20\x72\x65\x74\x20\x3d\x20\x30\x3b\0\x20\x20\x20\
 \x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\
 \x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\
-\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\
-\x20\x28\x65\x72\x72\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x69\x70\x76\x36\x5f\
-\x65\x78\x74\x5f\x64\x73\x74\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x7d\x20\x5f\x5f\x61\x74\x74\x72\x69\x62\x75\x74\x65\x5f\
-\x5f\x28\x28\x70\x61\x63\x6b\x65\x64\x29\x29\x20\x6f\x70\x74\x20\x3d\x20\x7b\
-\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\
-\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x3d\x20\x28\x6f\x70\x74\x2e\x74\
-\x79\x70\x65\x20\x3d\x3d\x20\x49\x50\x56\x36\x5f\x54\x4c\x56\x5f\x50\x41\x44\
-\x31\x29\x20\x3f\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x69\x66\x20\x28\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x20\x31\
-\x20\x3e\x3d\x20\x65\x78\x74\x5f\x68\x64\x72\x2e\x68\x64\x72\x6c\x65\x6e\x20\
-\x2a\x20\x38\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x2c\x20\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x72\x65\x74\x2c\x20\x73\x69\x7a\
+\x65\x6f\x66\x28\x72\x65\x74\x29\x2c\0\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\
+\x72\x29\x20\x7b\0\x20\x20\x20\x20\x73\x77\x69\x74\x63\x68\x20\x28\x62\x70\x66\
+\x5f\x6e\x74\x6f\x68\x73\x28\x72\x65\x74\x29\x29\x20\x7b\0\x20\x20\x20\x20\x20\
 \x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\
 \x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\
-\x6b\x62\x2c\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x20\x6f\x70\
-\x74\x5f\x6f\x66\x66\x73\x65\x74\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x6f\x70\x74\x2e\x74\x79\x70\x65\x20\
-\x3d\x3d\x20\x49\x50\x56\x36\x5f\x54\x4c\x56\x5f\x48\x41\x4f\x29\x20\x7b\0\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x20\x6f\x70\
-\x74\x5f\x6f\x66\x66\x73\x65\x74\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\
-\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\
-\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x29\x20\
-\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x69\x70\x76\x36\x5f\x65\x78\x74\
-\x5f\x73\x72\x63\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x66\x72\x61\x67\x6d\x65\x6e\x74\
-\x65\x64\x20\x3d\x20\x74\x72\x75\x65\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x2a\
-\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x3d\x20\x28\x65\x78\x74\x5f\x68\
-\x64\x72\x2e\x68\x64\x72\x6c\x65\x6e\x20\x2b\x20\x31\x29\x20\x2a\x20\x38\x3b\0\
-\x20\x20\x20\x20\x20\x20\x20\x20\x2a\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\x6f\
-\x6c\x20\x3d\x20\x65\x78\x74\x5f\x68\x64\x72\x2e\x6e\x65\x78\x74\x68\x64\x72\
-\x3b\0\x20\x20\x20\x20\x66\x6f\x72\x20\x28\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\
-\x69\x6e\x74\x20\x69\x20\x3d\x20\x30\x3b\x20\x69\x20\x3c\x20\x49\x50\x36\x5f\
-\x45\x58\x54\x45\x4e\x53\x49\x4f\x4e\x53\x5f\x43\x4f\x55\x4e\x54\x3b\x20\x2b\
-\x2b\x69\x29\x20\x7b\0\x20\x20\x20\x20\x7d\x20\x65\x6c\x73\x65\x20\x69\x66\x20\
-\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\x69\x70\x76\
-\x36\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\
-\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\x69\x70\x76\
-\x36\x5f\x65\x78\x74\x5f\x64\x73\x74\x20\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\
-\x6f\x2e\x69\x73\x5f\x69\x70\x76\x36\x5f\x65\x78\x74\x5f\x73\x72\x63\x20\x26\
-\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x65\x6c\x73\x65\x20\x69\x66\x20\
-\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\x75\x64\x70\
-\x20\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x65\x6c\x73\x65\x20\x69\
-\x66\x20\x28\x63\x6f\x6e\x66\x69\x67\x2d\x3e\x68\x61\x73\x68\x5f\x74\x79\x70\
-\x65\x73\x20\x26\x20\x56\x49\x52\x54\x49\x4f\x5f\x4e\x45\x54\x5f\x52\x53\x53\
-\x5f\x48\x41\x53\x48\x5f\x54\x59\x50\x45\x5f\x49\x50\x76\x34\x29\x20\x7b\0\x20\
-\x20\x20\x20\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x5f\x6d\x65\x6d\x63\x70\x79\
-\x28\x26\x72\x73\x73\x5f\x69\x6e\x70\x75\x74\x5b\x2a\x62\x79\x74\x65\x73\x5f\
-\x77\x72\x69\x74\x74\x65\x6e\x5d\x2c\x20\x70\x74\x72\x2c\x20\x73\x69\x7a\x65\
-\x29\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\
-\x3e\x69\x73\x5f\x75\x64\x70\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x75\x64\x70\x68\x64\x72\x20\
-\x75\x64\x70\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x6b\x62\x2c\x20\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x72\x65\x74\x2c\x20\x73\
+\x69\x7a\x65\x6f\x66\x28\x72\x65\x74\x29\x2c\0\x20\x20\x20\x20\x72\x65\x74\x75\
+\x72\x6e\x20\x72\x65\x74\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\x6c\x33\x5f\x70\
+\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x3d\x20\x30\x29\x20\x7b\0\x20\x20\x20\x20\
+\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x69\x70\x76\x34\x20\x3d\
+\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x69\
+\x70\x68\x64\x72\x20\x69\x70\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\
 \x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\
 \x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\
-\x62\x2c\x20\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x75\x64\x70\x2c\
-\x20\x73\x69\x7a\x65\x6f\x66\x28\x75\x64\x70\x29\x2c\0\x20\x20\x20\x20\x20\x20\
-\x20\x20\x7d\x20\x65\x6c\x73\x65\x20\x69\x66\x20\x28\x63\x6f\x6e\x66\x69\x67\
-\x2d\x3e\x68\x61\x73\x68\x5f\x74\x79\x70\x65\x73\x20\x26\x20\x56\x49\x52\x54\
-\x49\x4f\x5f\x4e\x45\x54\x5f\x52\x53\x53\x5f\x48\x41\x53\x48\x5f\x54\x59\x50\
-\x45\x5f\x49\x50\x76\x36\x29\x20\x7b\0\x20\x20\x20\x20\x66\x6f\x72\x20\x28\x62\
-\x79\x74\x65\x20\x3d\x20\x30\x3b\x20\x62\x79\x74\x65\x20\x3c\x20\x48\x41\x53\
-\x48\x5f\x43\x41\x4c\x43\x55\x4c\x41\x54\x49\x4f\x4e\x5f\x42\x55\x46\x46\x45\
-\x52\x5f\x53\x49\x5a\x45\x3b\x20\x62\x79\x74\x65\x2b\x2b\x29\x20\x7b\0\x20\x20\
-\x20\x20\x5f\x5f\x75\x33\x32\x20\x6c\x65\x66\x74\x6d\x6f\x73\x74\x5f\x33\x32\
-\x5f\x62\x69\x74\x73\x20\x3d\x20\x6b\x65\x79\x2d\x3e\x6c\x65\x66\x74\x6d\x6f\
-\x73\x74\x5f\x33\x32\x5f\x62\x69\x74\x73\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\
-\x5f\x5f\x75\x38\x20\x69\x6e\x70\x75\x74\x5f\x62\x79\x74\x65\x20\x3d\x20\x69\
-\x6e\x70\x75\x74\x5b\x62\x79\x74\x65\x5d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x69\x66\x20\x28\x69\x6e\x70\x75\x74\x5f\x62\x79\x74\x65\x20\
-\x26\x20\x28\x31\x20\x3c\x3c\x20\x37\x29\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\
-\x20\x20\x5f\x5f\x75\x38\x20\x6b\x65\x79\x5f\x62\x79\x74\x65\x20\x3d\x20\x6b\
-\x65\x79\x2d\x3e\x6e\x65\x78\x74\x5f\x62\x79\x74\x65\x5b\x62\x79\x74\x65\x5d\
-\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x28\x6c\x65\x66\x74\x6d\x6f\x73\x74\x5f\x33\x32\x5f\x62\x69\x74\x73\
-\x20\x3c\x3c\x20\x31\x29\x20\x7c\x20\x28\x28\x6b\x65\x79\x5f\x62\x79\x74\x65\
-\x20\x26\x20\x28\x31\x20\x3c\x3c\x20\x37\x29\x29\x20\x3e\x3e\x20\x37\x29\x3b\0\
-\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x68\x61\x73\x68\x29\x20\x7b\0\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x5f\x75\x33\x32\x20\x74\
-\x61\x62\x6c\x65\x5f\x69\x64\x78\x20\x3d\x20\x68\x61\x73\x68\x20\x25\x20\x63\
-\x6f\x6e\x66\x69\x67\x2d\x3e\x69\x6e\x64\x69\x72\x65\x63\x74\x69\x6f\x6e\x73\
-\x5f\x6c\x65\x6e\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x71\x75\
-\x65\x75\x65\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\
-\x70\x5f\x65\x6c\x65\x6d\x28\x26\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\
-\x5f\x69\x6e\x64\x69\x72\x65\x63\x74\x69\x6f\x6e\x5f\x74\x61\x62\x6c\x65\x2c\0\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x71\x75\x65\
-\x75\x65\x29\x20\x7b\0\x7d\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x2a\x71\x75\x65\x75\x65\x3b\0\x63\
-\x68\x61\x72\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x6c\x69\
-\x63\x65\x6e\x73\x65\0\x62\x70\x66\x5f\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\
-\x62\x70\x66\x5f\x73\x6f\x63\x6b\0\0\0\0\x9f\xeb\x01\0\x20\0\0\0\0\0\0\0\x14\0\
-\0\0\x14\0\0\0\x6c\x0c\0\0\x80\x0c\0\0\0\0\0\0\x08\0\0\0\x26\x02\0\0\x01\0\0\0\
-\0\0\0\0\x24\0\0\0\x10\0\0\0\x26\x02\0\0\xc6\0\0\0\0\0\0\0\x37\x02\0\0\x61\x02\
-\0\0\0\x50\x08\0\x10\0\0\0\x37\x02\0\0\x92\x02\0\0\x0b\x68\x08\0\x20\0\0\0\x37\
-\x02\0\0\0\0\0\0\0\0\0\0\x28\0\0\0\x37\x02\0\0\xa5\x02\0\0\x0e\x74\x08\0\x50\0\
-\0\0\x37\x02\0\0\xea\x02\0\0\x0b\x78\x08\0\x88\0\0\0\x37\x02\0\0\x2a\x03\0\0\
-\x10\x80\x08\0\x90\0\0\0\x37\x02\0\0\0\0\0\0\0\0\0\0\x98\0\0\0\x37\x02\0\0\x2a\
-\x03\0\0\x10\x80\x08\0\xa0\0\0\0\x37\x02\0\0\x43\x03\0\0\x16\x84\x08\0\xa8\0\0\
-\0\x37\x02\0\0\x43\x03\0\0\x0d\x84\x08\0\xc0\0\0\0\x37\x02\0\0\x64\x03\0\0\x0a\
-\xfc\x05\0\xe8\0\0\0\x37\x02\0\0\x9b\x03\0\0\x1f\x0c\x06\0\x38\x01\0\0\x37\x02\
-\0\0\xcb\x03\0\0\x0f\xa0\x04\0\x40\x01\0\0\x37\x02\0\0\xe4\x03\0\0\x0c\x20\x04\
-\0\x50\x01\0\0\x37\x02\0\0\0\0\0\0\0\0\0\0\x58\x01\0\0\x37\x02\0\0\xf8\x03\0\0\
-\x0b\x2c\x04\0\x90\x01\0\0\x37\x02\0\0\x3e\x04\0\0\x09\x34\x04\0\xa0\x01\0\0\
-\x37\x02\0\0\x4d\x04\0\0\x0d\x44\x04\0\xb8\x01\0\0\x37\x02\0\0\x4d\x04\0\0\x05\
-\x44\x04\0\xd8\x01\0\0\x37\x02\0\0\0\0\0\0\0\0\0\0\xe0\x01\0\0\x37\x02\0\0\x6b\
-\x04\0\0\x0f\x58\x04\0\x10\x02\0\0\x37\x02\0\0\x3e\x04\0\0\x09\x70\x04\0\x18\
-\x02\0\0\x37\x02\0\0\xb5\x04\0\0\x0c\x80\x04\0\x20\x02\0\0\x37\x02\0\0\xc5\x04\
-\0\0\x09\xbc\x04\0\x50\x02\0\0\x37\x02\0\0\xe1\x04\0\0\x17\xd4\x04\0\x60\x02\0\
-\0\x37\x02\0\0\xfc\x04\0\0\x16\xdc\x04\0\x80\x02\0\0\x37\x02\0\0\xe1\x04\0\0\
-\x17\xd4\x04\0\x88\x02\0\0\x37\x02\0\0\x1a\x05\0\0\x0f\xe0\x04\0\xc0\x02\0\0\
-\x37\x02\0\0\x5d\x05\0\0\x0d\xe8\x04\0\xc8\x02\0\0\x37\x02\0\0\x70\x05\0\0\x24\
-\0\x05\0\xd0\x02\0\0\x37\x02\0\0\x70\x05\0\0\x20\0\x05\0\xe0\x02\0\0\x37\x02\0\
-\0\x9d\x05\0\0\x1b\xf8\x04\0\xe8\x02\0\0\x37\x02\0\0\x9d\x05\0\0\x16\xf8\x04\0\
-\xf0\x02\0\0\x37\x02\0\0\xbe\x05\0\0\x1b\xfc\x04\0\xf8\x02\0\0\x37\x02\0\0\xbe\
-\x05\0\0\x16\xfc\x04\0\0\x03\0\0\x37\x02\0\0\xdf\x05\0\0\x1a\x08\x05\0\x08\x03\
-\0\0\x37\x02\0\0\x70\x05\0\0\x1d\0\x05\0\x10\x03\0\0\x37\x02\0\0\x02\x06\0\0\
-\x18\x0c\x05\0\x18\x03\0\0\x37\x02\0\0\x02\x06\0\0\x1c\x0c\x05\0\x30\x03\0\0\
-\x37\x02\0\0\x22\x06\0\0\x15\x68\x05\0\x40\x03\0\0\x37\x02\0\0\x22\x06\0\0\x1a\
-\x68\x05\0\x58\x03\0\0\x37\x02\0\0\x56\x06\0\0\x0d\x6c\x05\0\x78\x03\0\0\x37\
-\x02\0\0\x80\x06\0\0\x1a\x70\x05\0\x88\x03\0\0\x37\x02\0\0\x9e\x06\0\0\x1b\x78\
-\x05\0\xa8\x03\0\0\x37\x02\0\0\x80\x06\0\0\x1a\x70\x05\0\xb0\x03\0\0\x37\x02\0\
-\0\xc2\x06\0\0\x13\x7c\x05\0\xe8\x03\0\0\x37\x02\0\0\x13\x07\0\0\x11\x84\x05\0\
-\xf0\x03\0\0\x37\x02\0\0\0\0\0\0\0\0\0\0\x10\x04\0\0\x37\x02\0\0\x2a\x07\0\0\
-\x15\x28\x06\0\x18\x04\0\0\x37\x02\0\0\x2a\x07\0\0\x09\x28\x06\0\x20\x04\0\0\
-\x37\x02\0\0\0\0\0\0\0\0\0\0\x70\x04\0\0\x37\x02\0\0\x49\x07\0\0\x19\x2c\x06\0\
-\x80\x04\0\0\x37\x02\0\0\x49\x07\0\0\x20\x2c\x06\0\xa0\x04\0\0\x37\x02\0\0\0\0\
-\0\0\0\0\0\0\xf0\x04\0\0\x37\x02\0\0\x6b\x07\0\0\x17\x14\x05\0\0\x05\0\0\x37\
-\x02\0\0\x86\x07\0\0\x18\x1c\x05\0\x30\x05\0\0\x37\x02\0\0\x6b\x07\0\0\x17\x14\
-\x05\0\x48\x05\0\0\x37\x02\0\0\xa7\x07\0\0\x0f\x20\x05\0\x80\x05\0\0\x37\x02\0\
-\0\x5d\x05\0\0\x0d\x28\x05\0\x88\x05\0\0\x37\x02\0\0\xec\x07\0\0\x1d\x38\x05\0\
-\xc8\x05\0\0\x37\x02\0\0\x0f\x08\0\0\x1d\x3c\x05\0\x08\x06\0\0\x37\x02\0\0\x32\
-\x08\0\0\x1b\x44\x05\0\x10\x06\0\0\x37\x02\0\0\x55\x08\0\0\x05\x30\x02\0\x58\
-\x06\0\0\x37\x02\0\0\x6d\x08\0\0\x19\xb8\x02\0\xd0\x06\0\0\x37\x02\0\0\0\0\0\0\
-\0\0\0\0\xd8\x06\0\0\x37\x02\0\0\x93\x08\0\0\x0f\xc8\x02\0\x10\x07\0\0\x37\x02\
-\0\0\x5d\x05\0\0\x0d\xd0\x02\0\x20\x07\0\0\x37\x02\0\0\xd8\x08\0\0\x0d\xe0\x02\
-\0\x40\x07\0\0\x37\x02\0\0\x07\x09\0\0\x20\xe4\x02\0\x68\x07\0\0\x37\x02\0\0\
-\x33\x09\0\0\x13\xec\x02\0\xa8\x07\0\0\x37\x02\0\0\x13\x07\0\0\x11\xf4\x02\0\
-\xb0\x07\0\0\x37\x02\0\0\x7b\x09\0\0\x19\x04\x03\0\xb8\x07\0\0\x37\x02\0\0\x7b\
-\x09\0\0\x34\x04\x03\0\xe0\x07\0\0\x37\x02\0\0\xb1\x09\0\0\x15\x18\x03\0\xf0\
-\x07\0\0\x37\x02\0\0\xf2\x09\0\0\x17\x14\x03\0\x30\x08\0\0\x37\x02\0\0\x29\x0a\
-\0\0\x15\x24\x03\0\x38\x08\0\0\x37\x02\0\0\x44\x0a\0\0\x27\x34\x03\0\x70\x08\0\
-\0\x37\x02\0\0\x6f\x0a\0\0\x27\x50\x03\0\x80\x08\0\0\x37\x02\0\0\x9f\x0a\0\0\
-\x1c\xb4\x03\0\x88\x08\0\0\x37\x02\0\0\xdb\x0a\0\0\x20\xc0\x03\0\x98\x08\0\0\
-\x37\x02\0\0\xdb\x0a\0\0\x2f\xc0\x03\0\xa0\x08\0\0\x37\x02\0\0\xdb\x0a\0\0\x36\
-\xc0\x03\0\xa8\x08\0\0\x37\x02\0\0\xdb\x0a\0\0\x15\xc0\x03\0\x18\x09\0\0\x37\
-\x02\0\0\x17\x0b\0\0\x43\x64\x03\0\x38\x09\0\0\x37\x02\0\0\0\0\0\0\0\0\0\0\x40\
-\x09\0\0\x37\x02\0\0\x17\x0b\0\0\x17\x64\x03\0\x80\x09\0\0\x37\x02\0\0\x29\x0a\
-\0\0\x15\x6c\x03\0\x88\x09\0\0\x37\x02\0\0\x67\x0b\0\0\x19\x7c\x03\0\x90\x09\0\
-\0\x37\x02\0\0\x67\x0b\0\0\x15\x7c\x03\0\x98\x09\0\0\x37\x02\0\0\x97\x0b\0\0\
-\x19\x84\x03\0\xa0\x09\0\0\x37\x02\0\0\xc7\x0b\0\0\x1b\x80\x03\0\xe8\x09\0\0\
-\x37\x02\0\0\x02\x0c\0\0\x19\x94\x03\0\xf0\x09\0\0\x37\x02\0\0\x21\x0c\0\0\x2b\
-\xa4\x03\0\x10\x0a\0\0\x37\x02\0\0\x9f\x0a\0\0\x1f\xb4\x03\0\x30\x0a\0\0\x37\
-\x02\0\0\x50\x0c\0\0\x21\xd4\x03\0\x40\x0a\0\0\x37\x02\0\0\x78\x0c\0\0\x20\xe4\
-\x03\0\x48\x0a\0\0\x37\x02\0\0\x78\x0c\0\0\x2c\xe4\x03\0\x60\x0a\0\0\x37\x02\0\
-\0\x78\x0c\0\0\x14\xe4\x03\0\x70\x0a\0\0\x37\x02\0\0\xa8\x0c\0\0\x20\xe0\x03\0\
-\x80\x0a\0\0\x37\x02\0\0\x55\x08\0\0\x05\x30\x02\0\xb0\x0a\0\0\x37\x02\0\0\xd0\
-\x0c\0\0\x38\xc0\x02\0\xd0\x0a\0\0\x37\x02\0\0\xd0\x0c\0\0\x05\xc0\x02\0\xe8\
-\x0a\0\0\x37\x02\0\0\x55\x08\0\0\x05\x30\x02\0\xf8\x0a\0\0\x37\x02\0\0\x0e\x0d\
-\0\0\x1c\xc4\x06\0\x08\x0b\0\0\x37\x02\0\0\x0e\x0d\0\0\x10\xc4\x06\0\x10\x0b\0\
-\0\x37\x02\0\0\0\0\0\0\0\0\0\0\x60\x0b\0\0\x37\x02\0\0\x49\x07\0\0\x19\xc8\x06\
-\0\x68\x0b\0\0\x37\x02\0\0\x49\x07\0\0\x20\xc8\x06\0\xa0\x0b\0\0\x37\x02\0\0\
-\x34\x0d\0\0\x2d\0\x07\0\xb0\x0b\0\0\x37\x02\0\0\x34\x0d\0\0\x1d\0\x07\0\xb8\
-\x0b\0\0\x37\x02\0\0\x34\x0d\0\0\x2d\0\x07\0\xc8\x0b\0\0\x37\x02\0\0\x63\x0d\0\
-\0\x2d\xd4\x06\0\xf8\x0b\0\0\x37\x02\0\0\x63\x0d\0\0\x1d\xd4\x06\0\x08\x0c\0\0\
-\x37\x02\0\0\x63\x0d\0\0\x2d\xd4\x06\0\x18\x0c\0\0\x37\x02\0\0\0\0\0\0\0\0\0\0\
-\xe8\x0c\0\0\x37\x02\0\0\x92\x0d\0\0\x20\x68\x06\0\xf0\x0c\0\0\x37\x02\0\0\x92\
-\x0d\0\0\x27\x68\x06\0\x18\x0d\0\0\x37\x02\0\0\xbb\x0d\0\0\x27\xa4\x06\0\x20\
-\x0d\0\0\x37\x02\0\0\xbb\x0d\0\0\x14\xa4\x06\0\x28\x0d\0\0\x37\x02\0\0\x04\x0e\
-\0\0\x05\x98\x01\0\x38\x0d\0\0\x37\x02\0\0\x04\x0e\0\0\x05\x98\x01\0\x60\x0d\0\
-\0\x37\x02\0\0\0\0\0\0\0\0\0\0\x70\x0d\0\0\x37\x02\0\0\0\0\0\0\0\0\0\0\x80\x0d\
-\0\0\x37\x02\0\0\x92\x0d\0\0\x20\x44\x07\0\x88\x0d\0\0\x37\x02\0\0\x92\x0d\0\0\
-\x27\x44\x07\0\xc0\x0d\0\0\x37\x02\0\0\x34\x0d\0\0\x2d\x7c\x07\0\xd0\x0d\0\0\
-\x37\x02\0\0\x34\x0d\0\0\x1d\x7c\x07\0\xd8\x0d\0\0\x37\x02\0\0\x34\x0d\0\0\x2d\
-\x7c\x07\0\xe8\x0d\0\0\x37\x02\0\0\x63\x0d\0\0\x2d\x50\x07\0\x18\x0e\0\0\x37\
-\x02\0\0\x63\x0d\0\0\x1d\x50\x07\0\x28\x0e\0\0\x37\x02\0\0\x63\x0d\0\0\x2d\x50\
-\x07\0\x40\x0e\0\0\x37\x02\0\0\x41\x0e\0\0\x1a\xa0\x05\0\x50\x0e\0\0\x37\x02\0\
-\0\x5f\x0e\0\0\x1b\xa8\x05\0\x60\x0e\0\0\x37\x02\0\0\x41\x0e\0\0\x1a\xa0\x05\0\
-\x68\x0e\0\0\x37\x02\0\0\x83\x0e\0\0\x13\xac\x05\0\xa0\x0e\0\0\x37\x02\0\0\x13\
-\x07\0\0\x11\xb4\x05\0\xb0\x0e\0\0\x37\x02\0\0\x55\x08\0\0\x05\x30\x02\0\xc0\
-\x0e\0\0\x37\x02\0\0\xd4\x0e\0\0\x27\xc8\x07\0\xd0\x0e\0\0\x37\x02\0\0\xd4\x0e\
-\0\0\x14\xc8\x07\0\xf0\x0e\0\0\x37\x02\0\0\x63\x0d\0\0\x2d\xcc\x07\0\0\x0f\0\0\
-\x37\x02\0\0\x63\x0d\0\0\x1d\xcc\x07\0\x08\x0f\0\0\x37\x02\0\0\x63\x0d\0\0\x2d\
-\xcc\x07\0\x30\x0f\0\0\x37\x02\0\0\0\0\0\0\0\0\0\0\x80\x0f\0\0\x37\x02\0\0\x34\
-\x0d\0\0\x1d\xf8\x07\0\x88\x0f\0\0\x37\x02\0\0\x34\x0d\0\0\x2d\xf8\x07\0\x98\
-\x0f\0\0\x37\x02\0\0\x04\x0e\0\0\x05\x98\x01\0\xf0\x0f\0\0\x37\x02\0\0\x04\x0e\
-\0\0\x05\x98\x01\0\x30\x10\0\0\x37\x02\0\0\0\0\0\0\0\0\0\0\x48\x10\0\0\x37\x02\
-\0\0\x1d\x0f\0\0\x05\xd0\x01\0\x50\x10\0\0\x37\x02\0\0\x5f\x0f\0\0\x23\xc4\x01\
-\0\x68\x10\0\0\x37\x02\0\0\0\0\0\0\0\0\0\0\x70\x10\0\0\x37\x02\0\0\x93\x0f\0\0\
-\x1b\xd4\x01\0\x90\x10\0\0\x37\x02\0\0\xba\x0f\0\0\x11\xe8\x01\0\xa8\x10\0\0\
-\x37\x02\0\0\xe3\x0f\0\0\x19\xd8\x01\0\xc0\x10\0\0\x37\x02\0\0\x11\x10\0\0\x27\
-\xfc\x01\0\xc8\x10\0\0\x37\x02\0\0\x11\x10\0\0\x46\xfc\x01\0\xd8\x10\0\0\x37\
-\x02\0\0\x11\x10\0\0\x2d\xfc\x01\0\xe0\x10\0\0\x37\x02\0\0\xba\x0f\0\0\x11\xe8\
-\x01\0\x08\x11\0\0\x37\x02\0\0\x11\x10\0\0\x46\xfc\x01\0\x20\x11\0\0\x37\x02\0\
-\0\x11\x10\0\0\x27\xfc\x01\0\x28\x11\0\0\x37\x02\0\0\x11\x10\0\0\x2d\xfc\x01\0\
-\x30\x11\0\0\x37\x02\0\0\xba\x0f\0\0\x11\xe8\x01\0\x58\x11\0\0\x37\x02\0\0\x11\
-\x10\0\0\x27\xfc\x01\0\x60\x11\0\0\x37\x02\0\0\x11\x10\0\0\x46\xfc\x01\0\x78\
-\x11\0\0\x37\x02\0\0\x11\x10\0\0\x2d\xfc\x01\0\x80\x11\0\0\x37\x02\0\0\xba\x0f\
-\0\0\x11\xe8\x01\0\xa8\x11\0\0\x37\x02\0\0\x11\x10\0\0\x27\xfc\x01\0\xb0\x11\0\
-\0\x37\x02\0\0\x11\x10\0\0\x46\xfc\x01\0\xc8\x11\0\0\x37\x02\0\0\x11\x10\0\0\
-\x2d\xfc\x01\0\xd0\x11\0\0\x37\x02\0\0\xba\x0f\0\0\x11\xe8\x01\0\xf8\x11\0\0\
-\x37\x02\0\0\x11\x10\0\0\x46\xfc\x01\0\x10\x12\0\0\x37\x02\0\0\x11\x10\0\0\x27\
-\xfc\x01\0\x18\x12\0\0\x37\x02\0\0\x11\x10\0\0\x2d\xfc\x01\0\x20\x12\0\0\x37\
-\x02\0\0\xba\x0f\0\0\x11\xe8\x01\0\x48\x12\0\0\x37\x02\0\0\x11\x10\0\0\x46\xfc\
-\x01\0\x60\x12\0\0\x37\x02\0\0\x11\x10\0\0\x27\xfc\x01\0\x68\x12\0\0\x37\x02\0\
-\0\x11\x10\0\0\x2d\xfc\x01\0\x70\x12\0\0\x37\x02\0\0\xba\x0f\0\0\x11\xe8\x01\0\
-\x98\x12\0\0\x37\x02\0\0\x11\x10\0\0\x46\xfc\x01\0\xb0\x12\0\0\x37\x02\0\0\x11\
-\x10\0\0\x27\xfc\x01\0\xb8\x12\0\0\x37\x02\0\0\x11\x10\0\0\x2d\xfc\x01\0\xc0\
-\x12\0\0\x37\x02\0\0\xba\x0f\0\0\x11\xe8\x01\0\xe0\x12\0\0\x37\x02\0\0\x11\x10\
-\0\0\x46\xfc\x01\0\xe8\x12\0\0\x37\x02\0\0\x11\x10\0\0\x27\xfc\x01\0\xf0\x12\0\
-\0\x37\x02\0\0\x11\x10\0\0\x2d\xfc\x01\0\xf8\x12\0\0\x37\x02\0\0\x1d\x0f\0\0\
-\x3d\xd0\x01\0\x08\x13\0\0\x37\x02\0\0\x1d\x0f\0\0\x05\xd0\x01\0\x18\x13\0\0\
-\x37\x02\0\0\x5d\x10\0\0\x0d\x98\x08\0\x30\x13\0\0\x37\x02\0\0\x5d\x10\0\0\x0d\
-\x98\x08\0\x38\x13\0\0\x37\x02\0\0\x71\x10\0\0\x2e\x9c\x08\0\x58\x13\0\0\x37\
-\x02\0\0\x71\x10\0\0\x24\x9c\x08\0\x70\x13\0\0\x37\x02\0\0\x71\x10\0\0\x13\x9c\
-\x08\0\x80\x13\0\0\x37\x02\0\0\x71\x10\0\0\x2e\x9c\x08\0\x88\x13\0\0\x37\x02\0\
-\0\xb0\x10\0\0\x15\xa8\x08\0\xa0\x13\0\0\x37\x02\0\0\xf8\x10\0\0\x11\xb4\x08\0\
-\xa8\x13\0\0\x37\x02\0\0\0\0\0\0\0\0\0\0\xc8\x13\0\0\x37\x02\0\0\x11\x11\0\0\
-\x01\xd8\x08\0\xd0\x13\0\0\x37\x02\0\0\x13\x11\0\0\x18\xb8\x08\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\xde\0\0\0\0\0\x03\0\xc8\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7a\x01\0\0\0\
-\0\x03\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\0\0\0\0\0\x03\0\xa8\x13\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\xc7\0\0\0\0\0\x03\0\xd0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\x2c\x02\0\0\0\0\x03\0\x20\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf7\0\0\0\0\0\x03\0\
-\xe8\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1c\x02\0\0\0\0\x03\0\x10\x04\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\x28\x01\0\0\0\0\x03\0\xe0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf3\
-\x01\0\0\0\0\x03\0\x30\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xeb\x01\0\0\0\0\x03\0\
-\x38\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x44\x02\0\0\0\0\x03\0\xf0\x03\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\xe3\x01\0\0\0\0\x03\0\xf8\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x18\
-\x01\0\0\0\0\x03\0\xe8\x0c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x30\x01\0\0\0\0\x03\0\
-\xa0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xa9\x01\0\0\0\0\x03\0\x40\x10\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\x51\x01\0\0\0\0\x03\0\x78\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x5c\
-\x02\0\0\0\0\x03\0\xb0\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\x02\0\0\0\0\x03\0\
-\x50\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xc2\x01\0\0\0\0\x03\0\xc0\x06\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\x69\x01\0\0\0\0\x03\0\x20\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\
-\x01\0\0\0\0\x03\0\x60\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x38\x01\0\0\0\0\x03\0\
-\x30\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x20\x01\0\0\0\0\x03\0\x40\x0a\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\xba\x01\0\0\0\0\x03\0\xe0\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xa1\
-\x01\0\0\0\0\x03\0\x48\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\x01\0\0\0\0\x03\0\
-\x18\x09\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xfb\x01\0\0\0\0\x03\0\x80\x08\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\x99\x01\0\0\0\0\x03\0\xf8\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x59\
-\x01\0\0\0\0\x03\0\x50\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x54\x02\0\0\0\0\x03\0\
-\x08\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xef\0\0\0\0\0\x03\0\xe8\x0a\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\x4c\x02\0\0\0\0\x03\0\xb0\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x24\
-\x02\0\0\0\0\x03\0\xd8\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x89\x01\0\0\0\0\x03\0\
-\x80\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\x01\0\0\0\0\x03\0\xb0\x0b\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\xd6\0\0\0\0\0\x03\0\xc8\x0b\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x14\
-\x02\0\0\0\0\x03\0\xf8\x0b\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb2\x01\0\0\0\0\x03\0\
-\x18\x0c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xdb\x01\0\0\0\0\x03\0\x10\x0c\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\x3c\x02\0\0\0\0\x03\0\x18\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x91\
-\x01\0\0\0\0\x03\0\x60\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81\x01\0\0\0\0\x03\0\
-\xc0\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xe7\0\0\0\0\0\x03\0\xd0\x0d\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\x34\x02\0\0\0\0\x03\0\xe8\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd3\
-\x01\0\0\0\0\x03\0\x18\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\x01\0\0\0\0\x03\0\0\
-\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xce\0\0\0\0\0\x03\0\x18\x0f\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\x0b\x02\0\0\0\0\x03\0\xf0\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xca\x01\0\
-\0\0\0\x03\0\x30\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x01\0\0\0\0\x03\0\x60\x10\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x48\x01\0\0\0\0\x03\0\x18\x13\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\x64\x02\0\0\0\0\x03\0\xd0\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4e\0\0\0\
-\x12\0\x03\0\0\0\0\0\0\0\0\0\xe0\x13\0\0\0\0\0\0\x33\0\0\0\x11\0\x05\0\0\0\0\0\
-\0\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\x11\0\x05\0\x20\0\0\0\0\0\0\0\x20\0\0\0\0\
-\0\0\0\x90\0\0\0\x11\0\x05\0\x40\0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x87\0\0\0\x11\
-\0\x06\0\0\0\0\0\0\0\0\0\x07\0\0\0\0\0\0\0\x28\0\0\0\0\0\0\0\x01\0\0\0\x37\0\0\
-\0\x50\0\0\0\0\0\0\0\x01\0\0\0\x38\0\0\0\x88\x13\0\0\0\0\0\0\x01\0\0\0\x39\0\0\
-\0\xd8\x04\0\0\0\0\0\0\x04\0\0\0\x37\0\0\0\xe4\x04\0\0\0\0\0\0\x04\0\0\0\x38\0\
-\0\0\xf0\x04\0\0\0\0\0\0\x04\0\0\0\x39\0\0\0\x08\x05\0\0\0\0\0\0\x04\0\0\0\x3a\
-\0\0\0\x2c\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\0\0\0\0\0\0\0\x04\0\0\0\x01\0\
-\0\0\x50\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
-\0\x70\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
-\x90\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
-\xb0\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
-\xd0\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
-\xf0\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
-\x10\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
-\0\x30\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\
-\0\0\x50\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x01\0\0\0\0\0\0\x04\0\0\0\x01\
-\0\0\0\x70\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x01\0\0\0\0\0\0\x04\0\0\0\
-\x01\0\0\0\x90\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x01\0\0\0\0\0\0\x04\0\0\
-\0\x01\0\0\0\xb0\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x01\0\0\0\0\0\0\x04\0\
-\0\0\x01\0\0\0\xd0\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x01\0\0\0\0\0\0\x04\
-\0\0\0\x01\0\0\0\xf0\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x02\0\0\0\0\0\0\x04\
-\0\0\0\x01\0\0\0\x10\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x02\0\0\0\0\0\0\
-\x04\0\0\0\x01\0\0\0\x30\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x02\0\0\0\0\0\
-\0\x04\0\0\0\x01\0\0\0\x50\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x02\0\0\0\0\
-\0\0\x04\0\0\0\x01\0\0\0\x70\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x02\0\0\0\
-\0\0\0\x04\0\0\0\x01\0\0\0\x90\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x02\0\0\
-\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x02\0\
-\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x02\
-\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x03\
-\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\
-\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
-\x40\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
-\0\x60\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\
-\0\0\x80\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x03\0\0\0\0\0\0\x04\0\0\0\x01\
-\0\0\0\xa0\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x03\0\0\0\0\0\0\x04\0\0\0\
-\x01\0\0\0\xc0\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x03\0\0\0\0\0\0\x04\0\0\
-\0\x01\0\0\0\xe0\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x03\0\0\0\0\0\0\x04\0\
-\0\0\x01\0\0\0\0\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x04\0\0\0\0\0\0\x04\0\
-\0\0\x01\0\0\0\x20\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x04\0\0\0\0\0\0\x04\
-\0\0\0\x01\0\0\0\x40\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x04\0\0\0\0\0\0\
-\x04\0\0\0\x01\0\0\0\x60\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x04\0\0\0\0\0\
-\0\x04\0\0\0\x01\0\0\0\x80\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x04\0\0\0\0\
-\0\0\x04\0\0\0\x01\0\0\0\xa0\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x04\0\0\0\
-\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x04\0\0\
-\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x04\0\
-\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x05\0\
-\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x05\
-\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\
-\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
-\x70\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
-\0\x90\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\
-\0\0\xb0\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x05\0\0\0\0\0\0\x04\0\0\0\x01\
-\0\0\0\xd0\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x05\0\0\0\0\0\0\x04\0\0\0\
-\x01\0\0\0\xf0\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x06\0\0\0\0\0\0\x04\0\0\0\
-\x01\0\0\0\x10\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x06\0\0\0\0\0\0\x04\0\0\
-\0\x01\0\0\0\x30\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x06\0\0\0\0\0\0\x04\0\
-\0\0\x01\0\0\0\x50\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x06\0\0\0\0\0\0\x04\
-\0\0\0\x01\0\0\0\x70\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x06\0\0\0\0\0\0\
-\x04\0\0\0\x01\0\0\0\x90\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x06\0\0\0\0\0\
-\0\x04\0\0\0\x01\0\0\0\xb0\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x06\0\0\0\0\
-\0\0\x04\0\0\0\x01\0\0\0\xd0\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x06\0\0\0\
-\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x07\0\0\0\
-\0\0\0\x04\0\0\0\x01\0\0\0\x10\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x07\0\0\
-\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x07\0\
-\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x07\
-\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\
-\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
-\xa0\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
-\0\xc0\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\
-\0\0\xe0\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x07\0\0\0\0\0\0\x04\0\0\0\x01\
-\0\0\0\0\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x08\0\0\0\0\0\0\x04\0\0\0\x01\
-\0\0\0\x20\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x08\0\0\0\0\0\0\x04\0\0\0\
-\x01\0\0\0\x40\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x08\0\0\0\0\0\0\x04\0\0\
-\0\x01\0\0\0\x60\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x08\0\0\0\0\0\0\x04\0\
-\0\0\x01\0\0\0\x80\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x08\0\0\0\0\0\0\x04\
-\0\0\0\x01\0\0\0\xa0\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x08\0\0\0\0\0\0\
-\x04\0\0\0\x01\0\0\0\xc0\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x08\0\0\0\0\0\
-\0\x04\0\0\0\x01\0\0\0\xe0\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x08\0\0\0\0\
-\0\0\x04\0\0\0\x01\0\0\0\0\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x09\0\0\0\0\
-\0\0\x04\0\0\0\x01\0\0\0\x20\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x09\0\0\0\
-\0\0\0\x04\0\0\0\x01\0\0\0\x40\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x09\0\0\
-\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x09\0\
-\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x09\
-\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\
-\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
-\xd0\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
-\0\xf0\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
-\0\x10\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\
-\0\0\x30\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x0a\0\0\0\0\0\0\x04\0\0\0\x01\
-\0\0\0\x50\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x0a\0\0\0\0\0\0\x04\0\0\0\
-\x01\0\0\0\x70\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x0a\0\0\0\0\0\0\x04\0\0\
-\0\x01\0\0\0\x90\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x0a\0\0\0\0\0\0\x04\0\
-\0\0\x01\0\0\0\xb0\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x0a\0\0\0\0\0\0\x04\
-\0\0\0\x01\0\0\0\xd0\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x0a\0\0\0\0\0\0\
-\x04\0\0\0\x01\0\0\0\xf0\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x0b\0\0\0\0\0\0\
-\x04\0\0\0\x01\0\0\0\x10\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x0b\0\0\0\0\0\
-\0\x04\0\0\0\x01\0\0\0\x30\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x0b\0\0\0\0\
-\0\0\x04\0\0\0\x01\0\0\0\x50\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x0b\0\0\0\
-\0\0\0\x04\0\0\0\x01\0\0\0\x70\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x0b\0\0\
-\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x0b\0\
-\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x0b\
-\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\
-\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\
-\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
-\x20\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
-\0\x40\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\
-\0\0\x60\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x0c\0\0\0\0\0\0\x04\0\0\0\x01\
-\0\0\0\x80\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x0c\0\0\0\0\0\0\x04\0\0\0\
-\x01\0\0\0\x40\x41\x42\x43\x44\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\
-\x5f\x74\x6f\x65\x70\x6c\x69\x74\x7a\x5f\x6b\x65\x79\0\x2e\x74\x65\x78\x74\0\
-\x2e\x72\x65\x6c\x2e\x42\x54\x46\x2e\x65\x78\x74\0\x2e\x6d\x61\x70\x73\0\x74\
-\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x63\x6f\x6e\x66\x69\x67\x75\x72\
-\x61\x74\x69\x6f\x6e\x73\0\x74\x75\x6e\x5f\x72\x73\x73\x5f\x73\x74\x65\x65\x72\
-\x69\x6e\x67\x5f\x70\x72\x6f\x67\0\x2e\x72\x65\x6c\x74\x75\x6e\x5f\x72\x73\x73\
-\x5f\x73\x74\x65\x65\x72\x69\x6e\x67\0\x2e\x6c\x6c\x76\x6d\x5f\x61\x64\x64\x72\
-\x73\x69\x67\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x74\x61\x70\x5f\x72\x73\x73\
+\x62\x2c\x20\x30\x2c\x20\x26\x69\x70\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\x69\
+\x70\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x29\
+\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\
+\x66\x72\x61\x67\x6d\x65\x6e\x74\x65\x64\x20\x3d\x20\x21\x21\x69\x70\x2e\x66\
+\x72\x61\x67\x5f\x6f\x66\x66\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\
+\x6f\x2d\x3e\x69\x6e\x5f\x73\x72\x63\x20\x3d\x20\x69\x70\x2e\x73\x61\x64\x64\
+\x72\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x6e\x5f\
+\x64\x73\x74\x20\x3d\x20\x69\x70\x2e\x64\x61\x64\x64\x72\x3b\0\x20\x20\x20\x20\
+\x20\x20\x20\x20\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x20\x69\
+\x70\x2e\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\
+\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x3d\x20\x69\x70\x2e\x69\x68\x6c\x20\
+\x2a\x20\x34\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\x6c\x34\x5f\x70\x72\x6f\x74\
+\x6f\x63\x6f\x6c\x20\x21\x3d\x20\x30\x20\x26\x26\x20\x21\x69\x6e\x66\x6f\x2d\
+\x3e\x69\x73\x5f\x66\x72\x61\x67\x6d\x65\x6e\x74\x65\x64\x29\x20\x7b\0\x20\x20\
+\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\
+\x6f\x6c\x20\x3d\x3d\x20\x49\x50\x50\x52\x4f\x54\x4f\x5f\x54\x43\x50\x29\x20\
+\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\
+\x69\x73\x5f\x74\x63\x70\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x74\x63\x70\x68\x64\x72\x20\x74\
+\x63\x70\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\
+\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\
+\x2c\x20\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x74\x63\x70\x2c\x20\
+\x73\x69\x7a\x65\x6f\x66\x28\x74\x63\x70\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x29\x20\x7b\0\x20\x20\x20\x20\
+\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\
+\x69\x70\x76\x34\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\
+\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\x74\x63\x70\x20\
+\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\
+\x69\x70\x76\x36\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\
+\x72\x75\x63\x74\x20\x69\x70\x76\x36\x68\x64\x72\x20\x69\x70\x36\x20\x3d\x20\
+\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\
+\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\
+\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x30\x2c\x20\x26\x69\x70\x36\
+\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\x69\x70\x36\x29\x2c\0\x20\x20\x20\x20\x20\
+\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x6e\x36\x5f\x73\x72\x63\x20\x3d\x20\
+\x69\x70\x36\x2e\x73\x61\x64\x64\x72\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\
+\x6e\x66\x6f\x2d\x3e\x69\x6e\x36\x5f\x64\x73\x74\x20\x3d\x20\x69\x70\x36\x2e\
+\x64\x61\x64\x64\x72\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x6c\x34\x5f\x70\x72\
+\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x20\x69\x70\x36\x2e\x6e\x65\x78\x74\x68\x64\
+\x72\x3b\0\x20\x20\x20\x20\x73\x77\x69\x74\x63\x68\x20\x28\x68\x64\x72\x5f\x74\
+\x79\x70\x65\x29\x20\x7b\0\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x69\x70\
+\x76\x36\x5f\x6f\x70\x74\x5f\x68\x64\x72\x20\x65\x78\x74\x5f\x68\x64\x72\x20\
+\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\
+\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\
+\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x2a\x6c\x34\x5f\x6f\
+\x66\x66\x73\x65\x74\x2c\x20\x26\x65\x78\x74\x5f\x68\x64\x72\x2c\0\x20\x20\x20\
+\x20\x20\x20\x20\x20\x69\x66\x20\x28\x2a\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\
+\x6f\x6c\x20\x3d\x3d\x20\x49\x50\x50\x52\x4f\x54\x4f\x5f\x52\x4f\x55\x54\x49\
+\x4e\x47\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\
+\x72\x75\x63\x74\x20\x69\x70\x76\x36\x5f\x72\x74\x5f\x68\x64\x72\x20\x65\x78\
+\x74\x5f\x72\x74\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\
+\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\
+\x6b\x62\x2c\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x65\x78\
+\x74\x5f\x72\x74\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\
+\x20\x28\x28\x65\x78\x74\x5f\x72\x74\x2e\x74\x79\x70\x65\x20\x3d\x3d\x20\x49\
+\x50\x56\x36\x5f\x53\x52\x43\x52\x54\x5f\x54\x59\x50\x45\x5f\x32\x29\x20\x26\
+\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x20\x6f\x66\x66\x73\
+\x65\x74\x6f\x66\x28\x73\x74\x72\x75\x63\x74\x20\x72\x74\x32\x5f\x68\x64\x72\
+\x2c\x20\x61\x64\x64\x72\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\
+\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\
+\x28\x73\x6b\x62\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x69\x66\x20\x28\x65\x72\x72\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x69\
+\x70\x76\x36\x5f\x65\x78\x74\x5f\x64\x73\x74\x20\x3d\x20\x31\x3b\0\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x5f\x5f\x61\x74\x74\x72\x69\x62\
+\x75\x74\x65\x5f\x5f\x28\x28\x70\x61\x63\x6b\x65\x64\x29\x29\x20\x6f\x70\x74\
+\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x3d\x20\x28\x6f\
+\x70\x74\x2e\x74\x79\x70\x65\x20\x3d\x3d\x20\x49\x50\x56\x36\x5f\x54\x4c\x56\
+\x5f\x50\x41\x44\x31\x29\x20\x3f\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x69\x66\x20\x28\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\
+\x20\x2b\x20\x31\x20\x3e\x3d\x20\x65\x78\x74\x5f\x68\x64\x72\x2e\x68\x64\x72\
+\x6c\x65\x6e\x20\x2a\x20\x38\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\
+\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\
+\x76\x65\x28\x73\x6b\x62\x2c\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\
+\x2b\x20\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\x2c\0\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x6f\x70\x74\x2e\x74\
+\x79\x70\x65\x20\x3d\x3d\x20\x49\x50\x56\x36\x5f\x54\x4c\x56\x5f\x48\x41\x4f\
+\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\
+\x2b\x20\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\0\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\
+\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\
+\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\0\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\
+\x72\x72\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x69\x70\x76\x36\
+\x5f\x65\x78\x74\x5f\x73\x72\x63\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x66\x72\x61\x67\
+\x6d\x65\x6e\x74\x65\x64\x20\x3d\x20\x74\x72\x75\x65\x3b\0\x20\x20\x20\x20\x20\
+\x20\x20\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x3d\x20\x28\x65\
+\x78\x74\x5f\x68\x64\x72\x2e\x68\x64\x72\x6c\x65\x6e\x20\x2b\x20\x31\x29\x20\
+\x2a\x20\x38\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x2a\x6c\x34\x5f\x70\x72\x6f\
+\x74\x6f\x63\x6f\x6c\x20\x3d\x20\x65\x78\x74\x5f\x68\x64\x72\x2e\x6e\x65\x78\
+\x74\x68\x64\x72\x3b\0\x20\x20\x20\x20\x66\x6f\x72\x20\x28\x75\x6e\x73\x69\x67\
+\x6e\x65\x64\x20\x69\x6e\x74\x20\x69\x20\x3d\x20\x30\x3b\x20\x69\x20\x3c\x20\
+\x49\x50\x36\x5f\x45\x58\x54\x45\x4e\x53\x49\x4f\x4e\x53\x5f\x43\x4f\x55\x4e\
+\x54\x3b\x20\x2b\x2b\x69\x29\x20\x7b\0\x20\x20\x20\x20\x7d\x20\x65\x6c\x73\x65\
+\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\
+\x5f\x69\x70\x76\x36\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\
+\x5f\x69\x70\x76\x36\x5f\x65\x78\x74\x5f\x64\x73\x74\x20\x26\x26\0\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\
+\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\x69\x70\x76\x36\x5f\x65\x78\x74\x5f\x73\
+\x72\x63\x20\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x65\x6c\x73\x65\
+\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\
+\x5f\x75\x64\x70\x20\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x65\x6c\
+\x73\x65\x20\x69\x66\x20\x28\x63\x6f\x6e\x66\x69\x67\x2d\x3e\x68\x61\x73\x68\
+\x5f\x74\x79\x70\x65\x73\x20\x26\x20\x56\x49\x52\x54\x49\x4f\x5f\x4e\x45\x54\
+\x5f\x52\x53\x53\x5f\x48\x41\x53\x48\x5f\x54\x59\x50\x45\x5f\x49\x50\x76\x34\
+\x29\x20\x7b\0\x20\x20\x20\x20\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x5f\x6d\x65\
+\x6d\x63\x70\x79\x28\x26\x72\x73\x73\x5f\x69\x6e\x70\x75\x74\x5b\x2a\x62\x79\
+\x74\x65\x73\x5f\x77\x72\x69\x74\x74\x65\x6e\x5d\x2c\x20\x70\x74\x72\x2c\x20\
+\x73\x69\x7a\x65\x29\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\
+\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x75\x64\x70\x20\x3d\x20\x31\x3b\0\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x75\x64\x70\
+\x68\x64\x72\x20\x75\x64\x70\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\
+\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\
+\x65\x28\x73\x6b\x62\x2c\x20\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\
+\x75\x64\x70\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\x75\x64\x70\x29\x2c\0\x20\x20\
+\x20\x20\x20\x20\x20\x20\x7d\x20\x65\x6c\x73\x65\x20\x69\x66\x20\x28\x63\x6f\
+\x6e\x66\x69\x67\x2d\x3e\x68\x61\x73\x68\x5f\x74\x79\x70\x65\x73\x20\x26\x20\
+\x56\x49\x52\x54\x49\x4f\x5f\x4e\x45\x54\x5f\x52\x53\x53\x5f\x48\x41\x53\x48\
+\x5f\x54\x59\x50\x45\x5f\x49\x50\x76\x36\x29\x20\x7b\0\x20\x20\x20\x20\x66\x6f\
+\x72\x20\x28\x62\x79\x74\x65\x20\x3d\x20\x30\x3b\x20\x62\x79\x74\x65\x20\x3c\
+\x20\x48\x41\x53\x48\x5f\x43\x41\x4c\x43\x55\x4c\x41\x54\x49\x4f\x4e\x5f\x42\
+\x55\x46\x46\x45\x52\x5f\x53\x49\x5a\x45\x3b\x20\x62\x79\x74\x65\x2b\x2b\x29\
+\x20\x7b\0\x20\x20\x20\x20\x5f\x5f\x75\x33\x32\x20\x6c\x65\x66\x74\x6d\x6f\x73\
+\x74\x5f\x33\x32\x5f\x62\x69\x74\x73\x20\x3d\x20\x6b\x65\x79\x2d\x3e\x6c\x65\
+\x66\x74\x6d\x6f\x73\x74\x5f\x33\x32\x5f\x62\x69\x74\x73\x3b\0\x20\x20\x20\x20\
+\x20\x20\x20\x20\x5f\x5f\x75\x38\x20\x69\x6e\x70\x75\x74\x5f\x62\x79\x74\x65\
+\x20\x3d\x20\x69\x6e\x70\x75\x74\x5b\x62\x79\x74\x65\x5d\x3b\0\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x69\x6e\x70\x75\x74\x5f\x62\
+\x79\x74\x65\x20\x26\x20\x28\x31\x20\x3c\x3c\x20\x37\x29\x29\x20\x7b\0\x20\x20\
+\x20\x20\x20\x20\x20\x20\x5f\x5f\x75\x38\x20\x6b\x65\x79\x5f\x62\x79\x74\x65\
+\x20\x3d\x20\x6b\x65\x79\x2d\x3e\x6e\x65\x78\x74\x5f\x62\x79\x74\x65\x5b\x62\
+\x79\x74\x65\x5d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x28\x6c\x65\x66\x74\x6d\x6f\x73\x74\x5f\x33\x32\x5f\
+\x62\x69\x74\x73\x20\x3c\x3c\x20\x31\x29\x20\x7c\x20\x28\x28\x6b\x65\x79\x5f\
+\x62\x79\x74\x65\x20\x26\x20\x28\x31\x20\x3c\x3c\x20\x37\x29\x29\x20\x3e\x3e\
+\x20\x37\x29\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x5f\x75\
+\x33\x32\x20\x74\x61\x62\x6c\x65\x5f\x69\x64\x78\x20\x3d\x20\x68\x61\x73\x68\
+\x20\x25\x20\x63\x6f\x6e\x66\x69\x67\x2d\x3e\x69\x6e\x64\x69\x72\x65\x63\x74\
+\x69\x6f\x6e\x73\x5f\x6c\x65\x6e\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x71\x75\x65\x75\x65\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\
+\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x74\x61\x70\x5f\x72\x73\x73\
 \x5f\x6d\x61\x70\x5f\x69\x6e\x64\x69\x72\x65\x63\x74\x69\x6f\x6e\x5f\x74\x61\
-\x62\x6c\x65\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\x62\0\x2e\
-\x72\x65\x6c\x2e\x42\x54\x46\0\x4c\x42\x42\x30\x5f\x39\0\x4c\x42\x42\x30\x5f\
-\x39\x39\0\x4c\x42\x42\x30\x5f\x37\x39\0\x4c\x42\x42\x30\x5f\x31\x30\x39\0\x4c\
-\x42\x42\x30\x5f\x38\x38\0\x4c\x42\x42\x30\x5f\x34\x38\0\x4c\x42\x42\x30\x5f\
-\x31\x38\0\x4c\x42\x42\x30\x5f\x31\x30\x38\0\x4c\x42\x42\x30\x5f\x39\x37\0\x4c\
-\x42\x42\x30\x5f\x37\x37\0\x4c\x42\x42\x30\x5f\x36\x37\0\x4c\x42\x42\x30\x5f\
-\x34\x37\0\x4c\x42\x42\x30\x5f\x31\x37\0\x4c\x42\x42\x30\x5f\x36\x36\0\x4c\x42\
-\x42\x30\x5f\x34\x36\0\x4c\x42\x42\x30\x5f\x33\x36\0\x4c\x42\x42\x30\x5f\x31\
-\x30\x36\0\x4c\x42\x42\x30\x5f\x35\x35\0\x4c\x42\x42\x30\x5f\x34\x35\0\x4c\x42\
-\x42\x30\x5f\x33\x35\0\x4c\x42\x42\x30\x5f\x32\x35\0\x4c\x42\x42\x30\x5f\x31\
-\x30\x35\0\x4c\x42\x42\x30\x5f\x34\0\x4c\x42\x42\x30\x5f\x39\x34\0\x4c\x42\x42\
-\x30\x5f\x38\x34\0\x4c\x42\x42\x30\x5f\x35\x34\0\x4c\x42\x42\x30\x5f\x34\x34\0\
-\x4c\x42\x42\x30\x5f\x33\x34\0\x4c\x42\x42\x30\x5f\x31\x30\x34\0\x4c\x42\x42\
-\x30\x5f\x38\x33\0\x4c\x42\x42\x30\x5f\x35\x33\0\x4c\x42\x42\x30\x5f\x32\x33\0\
-\x4c\x42\x42\x30\x5f\x31\x30\x33\0\x4c\x42\x42\x30\x5f\x39\x32\0\x4c\x42\x42\
-\x30\x5f\x38\x32\0\x4c\x42\x42\x30\x5f\x37\x32\0\x4c\x42\x42\x30\x5f\x36\x32\0\
-\x4c\x42\x42\x30\x5f\x35\x32\0\x4c\x42\x42\x30\x5f\x34\x32\0\x4c\x42\x42\x30\
-\x5f\x32\x32\0\x4c\x42\x42\x30\x5f\x31\x30\x32\0\x4c\x42\x42\x30\x5f\x38\x31\0\
-\x4c\x42\x42\x30\x5f\x36\x31\0\x4c\x42\x42\x30\x5f\x35\x31\0\x4c\x42\x42\x30\
-\x5f\x31\x31\0\x4c\x42\x42\x30\x5f\x39\x30\0\x4c\x42\x42\x30\x5f\x37\x30\0\x4c\
-\x42\x42\x30\x5f\x36\x30\0\x4c\x42\x42\x30\x5f\x35\x30\0\x4c\x42\x42\x30\x5f\
-\x34\x30\0\x4c\x42\x42\x30\x5f\x32\x30\0\x4c\x42\x42\x30\x5f\x31\x31\x30\0\0\0\
+\x62\x6c\x65\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\
+\x28\x71\x75\x65\x75\x65\x29\x20\x7b\0\x7d\0\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x2a\x71\x75\x65\
+\x75\x65\x3b\0\x63\x68\x61\x72\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\
+\x70\x73\0\x6c\x69\x63\x65\x6e\x73\x65\0\x62\x70\x66\x5f\x66\x6c\x6f\x77\x5f\
+\x6b\x65\x79\x73\0\x62\x70\x66\x5f\x73\x6f\x63\x6b\0\0\0\x9f\xeb\x01\0\x20\0\0\
+\0\0\0\0\0\x14\0\0\0\x14\0\0\0\x8c\x0c\0\0\xa0\x0c\0\0\0\0\0\0\x08\0\0\0\x6b\
+\x02\0\0\x01\0\0\0\0\0\0\0\x26\0\0\0\x10\0\0\0\x6b\x02\0\0\xc8\0\0\0\0\0\0\0\
+\x72\x02\0\0\x9e\x02\0\0\0\x5c\x08\0\x10\0\0\0\x72\x02\0\0\xcf\x02\0\0\x0b\x74\
+\x08\0\x20\0\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x28\0\0\0\x72\x02\0\0\xe2\x02\0\0\
+\x0e\x80\x08\0\x50\0\0\0\x72\x02\0\0\x27\x03\0\0\x0b\x84\x08\0\x88\0\0\0\x72\
+\x02\0\0\x67\x03\0\0\x10\x8c\x08\0\x90\0\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x98\0\
+\0\0\x72\x02\0\0\x67\x03\0\0\x10\x8c\x08\0\xa0\0\0\0\x72\x02\0\0\x80\x03\0\0\
+\x16\x90\x08\0\xa8\0\0\0\x72\x02\0\0\x80\x03\0\0\x0d\x90\x08\0\xc0\0\0\0\x72\
+\x02\0\0\xa1\x03\0\0\x0a\x04\x06\0\xe8\0\0\0\x72\x02\0\0\xd8\x03\0\0\x1f\x10\
+\x06\0\x38\x01\0\0\x72\x02\0\0\x08\x04\0\0\x0f\xa0\x04\0\x40\x01\0\0\x72\x02\0\
+\0\x21\x04\0\0\x0c\x20\x04\0\x50\x01\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x58\x01\0\
+\0\x72\x02\0\0\x35\x04\0\0\x0b\x2c\x04\0\x80\x01\0\0\x72\x02\0\0\x7b\x04\0\0\
+\x09\x34\x04\0\x90\x01\0\0\x72\x02\0\0\x7b\x04\0\0\x09\x34\x04\0\xa0\x01\0\0\
+\x72\x02\0\0\x8a\x04\0\0\x0d\x44\x04\0\xb8\x01\0\0\x72\x02\0\0\x8a\x04\0\0\x05\
+\x44\x04\0\xd8\x01\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\xe0\x01\0\0\x72\x02\0\0\xa8\
+\x04\0\0\x0f\x58\x04\0\0\x02\0\0\x72\x02\0\0\x7b\x04\0\0\x09\x70\x04\0\x10\x02\
+\0\0\x72\x02\0\0\x7b\x04\0\0\x09\x70\x04\0\x18\x02\0\0\x72\x02\0\0\xf2\x04\0\0\
+\x0c\x80\x04\0\x20\x02\0\0\x72\x02\0\0\x02\x05\0\0\x09\xbc\x04\0\x50\x02\0\0\
+\x72\x02\0\0\x1e\x05\0\0\x17\xd4\x04\0\x60\x02\0\0\x72\x02\0\0\x39\x05\0\0\x16\
+\xdc\x04\0\x80\x02\0\0\x72\x02\0\0\x1e\x05\0\0\x17\xd4\x04\0\x88\x02\0\0\x72\
+\x02\0\0\x57\x05\0\0\x0f\xe0\x04\0\xb0\x02\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\xe8\
+\x04\0\xc0\x02\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\xe8\x04\0\xc8\x02\0\0\x72\x02\0\
+\0\xad\x05\0\0\x24\0\x05\0\xd0\x02\0\0\x72\x02\0\0\xad\x05\0\0\x20\0\x05\0\xe0\
+\x02\0\0\x72\x02\0\0\xda\x05\0\0\x1b\xf8\x04\0\xe8\x02\0\0\x72\x02\0\0\xda\x05\
+\0\0\x16\xf8\x04\0\xf0\x02\0\0\x72\x02\0\0\xfb\x05\0\0\x1b\xfc\x04\0\xf8\x02\0\
+\0\x72\x02\0\0\xfb\x05\0\0\x16\xfc\x04\0\0\x03\0\0\x72\x02\0\0\x1c\x06\0\0\x1a\
+\x08\x05\0\x08\x03\0\0\x72\x02\0\0\xad\x05\0\0\x1d\0\x05\0\x10\x03\0\0\x72\x02\
+\0\0\x3f\x06\0\0\x18\x0c\x05\0\x18\x03\0\0\x72\x02\0\0\x3f\x06\0\0\x1c\x0c\x05\
+\0\x30\x03\0\0\x72\x02\0\0\x5f\x06\0\0\x15\x68\x05\0\x40\x03\0\0\x72\x02\0\0\
+\x5f\x06\0\0\x1a\x68\x05\0\x58\x03\0\0\x72\x02\0\0\x93\x06\0\0\x0d\x6c\x05\0\
+\x78\x03\0\0\x72\x02\0\0\xbd\x06\0\0\x1a\x70\x05\0\x88\x03\0\0\x72\x02\0\0\xdb\
+\x06\0\0\x1b\x78\x05\0\xa8\x03\0\0\x72\x02\0\0\xbd\x06\0\0\x1a\x70\x05\0\xb0\
+\x03\0\0\x72\x02\0\0\xff\x06\0\0\x13\x7c\x05\0\xd8\x03\0\0\x72\x02\0\0\x50\x07\
+\0\0\x11\x84\x05\0\xe8\x03\0\0\x72\x02\0\0\x50\x07\0\0\x11\x84\x05\0\xf0\x03\0\
+\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x10\x04\0\0\x72\x02\0\0\x67\x07\0\0\x15\x2c\x06\
+\0\x18\x04\0\0\x72\x02\0\0\x67\x07\0\0\x09\x2c\x06\0\x20\x04\0\0\x72\x02\0\0\0\
+\0\0\0\0\0\0\0\x70\x04\0\0\x72\x02\0\0\x86\x07\0\0\x19\x30\x06\0\x80\x04\0\0\
+\x72\x02\0\0\x86\x07\0\0\x20\x30\x06\0\xa0\x04\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\
+\xf0\x04\0\0\x72\x02\0\0\xa8\x07\0\0\x17\x14\x05\0\0\x05\0\0\x72\x02\0\0\xc3\
+\x07\0\0\x18\x1c\x05\0\x30\x05\0\0\x72\x02\0\0\xa8\x07\0\0\x17\x14\x05\0\x48\
+\x05\0\0\x72\x02\0\0\xe4\x07\0\0\x0f\x20\x05\0\x70\x05\0\0\x72\x02\0\0\x9a\x05\
+\0\0\x0d\x28\x05\0\x80\x05\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\x28\x05\0\x88\x05\0\
+\0\x72\x02\0\0\x29\x08\0\0\x1d\x38\x05\0\xc8\x05\0\0\x72\x02\0\0\x4c\x08\0\0\
+\x1d\x3c\x05\0\x08\x06\0\0\x72\x02\0\0\x6f\x08\0\0\x1b\x44\x05\0\x10\x06\0\0\
+\x72\x02\0\0\x92\x08\0\0\x05\x30\x02\0\x58\x06\0\0\x72\x02\0\0\xaa\x08\0\0\x19\
+\xb8\x02\0\xd0\x06\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\xd8\x06\0\0\x72\x02\0\0\xd0\
+\x08\0\0\x0f\xc8\x02\0\0\x07\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\xd0\x02\0\x18\x07\
+\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\xd0\x02\0\x20\x07\0\0\x72\x02\0\0\x15\x09\0\0\
+\x0d\xe0\x02\0\x40\x07\0\0\x72\x02\0\0\x44\x09\0\0\x20\xe4\x02\0\x68\x07\0\0\
+\x72\x02\0\0\x70\x09\0\0\x13\xec\x02\0\x90\x07\0\0\x72\x02\0\0\x50\x07\0\0\x11\
+\xf4\x02\0\xa8\x07\0\0\x72\x02\0\0\x50\x07\0\0\x11\xf4\x02\0\xb0\x07\0\0\x72\
+\x02\0\0\xb8\x09\0\0\x19\x04\x03\0\xb8\x07\0\0\x72\x02\0\0\xb8\x09\0\0\x34\x04\
+\x03\0\xe0\x07\0\0\x72\x02\0\0\xee\x09\0\0\x15\x18\x03\0\xf0\x07\0\0\x72\x02\0\
+\0\x2f\x0a\0\0\x17\x14\x03\0\x18\x08\0\0\x72\x02\0\0\x66\x0a\0\0\x15\x24\x03\0\
+\x30\x08\0\0\x72\x02\0\0\x66\x0a\0\0\x15\x24\x03\0\x38\x08\0\0\x72\x02\0\0\x81\
+\x0a\0\0\x27\x34\x03\0\x70\x08\0\0\x72\x02\0\0\xac\x0a\0\0\x27\x50\x03\0\x80\
+\x08\0\0\x72\x02\0\0\xdc\x0a\0\0\x1c\xb4\x03\0\x88\x08\0\0\x72\x02\0\0\x18\x0b\
+\0\0\x20\xc0\x03\0\x98\x08\0\0\x72\x02\0\0\x18\x0b\0\0\x2f\xc0\x03\0\xa0\x08\0\
+\0\x72\x02\0\0\x18\x0b\0\0\x36\xc0\x03\0\xa8\x08\0\0\x72\x02\0\0\x18\x0b\0\0\
+\x15\xc0\x03\0\x18\x09\0\0\x72\x02\0\0\x54\x0b\0\0\x43\x64\x03\0\x38\x09\0\0\
+\x72\x02\0\0\0\0\0\0\0\0\0\0\x40\x09\0\0\x72\x02\0\0\x54\x0b\0\0\x17\x64\x03\0\
+\x68\x09\0\0\x72\x02\0\0\x66\x0a\0\0\x15\x6c\x03\0\x80\x09\0\0\x72\x02\0\0\x66\
+\x0a\0\0\x15\x6c\x03\0\x88\x09\0\0\x72\x02\0\0\xa4\x0b\0\0\x19\x7c\x03\0\x90\
+\x09\0\0\x72\x02\0\0\xa4\x0b\0\0\x15\x7c\x03\0\x98\x09\0\0\x72\x02\0\0\xd4\x0b\
+\0\0\x19\x84\x03\0\xa0\x09\0\0\x72\x02\0\0\x04\x0c\0\0\x1b\x80\x03\0\xd0\x09\0\
+\0\x72\x02\0\0\x3f\x0c\0\0\x19\x94\x03\0\xe8\x09\0\0\x72\x02\0\0\x3f\x0c\0\0\
+\x19\x94\x03\0\xf0\x09\0\0\x72\x02\0\0\x5e\x0c\0\0\x2b\xa4\x03\0\x10\x0a\0\0\
+\x72\x02\0\0\xdc\x0a\0\0\x1f\xb4\x03\0\x30\x0a\0\0\x72\x02\0\0\x8d\x0c\0\0\x21\
+\xd4\x03\0\x40\x0a\0\0\x72\x02\0\0\xb5\x0c\0\0\x20\xe4\x03\0\x48\x0a\0\0\x72\
+\x02\0\0\xb5\x0c\0\0\x2c\xe4\x03\0\x60\x0a\0\0\x72\x02\0\0\xb5\x0c\0\0\x14\xe4\
+\x03\0\x70\x0a\0\0\x72\x02\0\0\xe5\x0c\0\0\x20\xe0\x03\0\x80\x0a\0\0\x72\x02\0\
+\0\x92\x08\0\0\x05\x30\x02\0\xb0\x0a\0\0\x72\x02\0\0\x0d\x0d\0\0\x38\xc0\x02\0\
+\xd0\x0a\0\0\x72\x02\0\0\x0d\x0d\0\0\x05\xc0\x02\0\xe8\x0a\0\0\x72\x02\0\0\x92\
+\x08\0\0\x05\x30\x02\0\xf8\x0a\0\0\x72\x02\0\0\x4b\x0d\0\0\x1c\xc8\x06\0\x08\
+\x0b\0\0\x72\x02\0\0\x4b\x0d\0\0\x10\xc8\x06\0\x10\x0b\0\0\x72\x02\0\0\0\0\0\0\
+\0\0\0\0\x60\x0b\0\0\x72\x02\0\0\x86\x07\0\0\x19\xcc\x06\0\x68\x0b\0\0\x72\x02\
+\0\0\x86\x07\0\0\x20\xcc\x06\0\xa0\x0b\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\x04\x07\
+\0\xb0\x0b\0\0\x72\x02\0\0\x71\x0d\0\0\x1d\x04\x07\0\xb8\x0b\0\0\x72\x02\0\0\
+\x71\x0d\0\0\x2d\x04\x07\0\xc8\x0b\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\xd8\x06\0\
+\xf8\x0b\0\0\x72\x02\0\0\xa0\x0d\0\0\x1d\xd8\x06\0\x08\x0c\0\0\x72\x02\0\0\xa0\
+\x0d\0\0\x2d\xd8\x06\0\x18\x0c\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\xe8\x0c\0\0\x72\
+\x02\0\0\xcf\x0d\0\0\x20\x6c\x06\0\xf0\x0c\0\0\x72\x02\0\0\xcf\x0d\0\0\x27\x6c\
+\x06\0\x18\x0d\0\0\x72\x02\0\0\xf8\x0d\0\0\x27\xa8\x06\0\x20\x0d\0\0\x72\x02\0\
+\0\xf8\x0d\0\0\x14\xa8\x06\0\x28\x0d\0\0\x72\x02\0\0\x41\x0e\0\0\x05\x98\x01\0\
+\x38\x0d\0\0\x72\x02\0\0\x41\x0e\0\0\x05\x98\x01\0\x60\x0d\0\0\x72\x02\0\0\x9a\
+\x05\0\0\x0d\x54\x05\0\x70\x0d\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x80\x0d\0\0\x72\
+\x02\0\0\xcf\x0d\0\0\x20\x48\x07\0\x88\x0d\0\0\x72\x02\0\0\xcf\x0d\0\0\x27\x48\
+\x07\0\xc0\x0d\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\x80\x07\0\xd0\x0d\0\0\x72\x02\0\
+\0\x71\x0d\0\0\x1d\x80\x07\0\xd8\x0d\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\x80\x07\0\
+\xe8\x0d\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\x54\x07\0\x18\x0e\0\0\x72\x02\0\0\xa0\
+\x0d\0\0\x1d\x54\x07\0\x28\x0e\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\x54\x07\0\x40\
+\x0e\0\0\x72\x02\0\0\x7e\x0e\0\0\x1a\xa0\x05\0\x50\x0e\0\0\x72\x02\0\0\x9c\x0e\
+\0\0\x1b\xa8\x05\0\x60\x0e\0\0\x72\x02\0\0\x7e\x0e\0\0\x1a\xa0\x05\0\x68\x0e\0\
+\0\x72\x02\0\0\xc0\x0e\0\0\x13\xac\x05\0\x90\x0e\0\0\x72\x02\0\0\x50\x07\0\0\
+\x11\xb4\x05\0\xa0\x0e\0\0\x72\x02\0\0\x50\x07\0\0\x11\xb4\x05\0\xb0\x0e\0\0\
+\x72\x02\0\0\x92\x08\0\0\x05\x30\x02\0\xc0\x0e\0\0\x72\x02\0\0\x11\x0f\0\0\x27\
+\xcc\x07\0\xd0\x0e\0\0\x72\x02\0\0\x11\x0f\0\0\x14\xcc\x07\0\xf0\x0e\0\0\x72\
+\x02\0\0\xa0\x0d\0\0\x2d\xd0\x07\0\0\x0f\0\0\x72\x02\0\0\xa0\x0d\0\0\x1d\xd0\
+\x07\0\x08\x0f\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\xd0\x07\0\x30\x0f\0\0\x72\x02\0\
+\0\0\0\0\0\0\0\0\0\x80\x0f\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x90\x0f\0\0\x72\x02\
+\0\0\x71\x0d\0\0\x1d\xfc\x07\0\x98\x0f\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\xfc\x07\
+\0\xa8\x0f\0\0\x72\x02\0\0\x41\x0e\0\0\x05\x98\x01\0\xf8\x0f\0\0\x72\x02\0\0\
+\x41\x0e\0\0\x05\x98\x01\0\x30\x10\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x40\x10\0\0\
+\x72\x02\0\0\x5a\x0f\0\0\x05\xd0\x01\0\x48\x10\0\0\x72\x02\0\0\x9c\x0f\0\0\x23\
+\xc4\x01\0\x60\x10\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x68\x10\0\0\x72\x02\0\0\xd0\
+\x0f\0\0\x1b\xd4\x01\0\x88\x10\0\0\x72\x02\0\0\xf7\x0f\0\0\x11\xe8\x01\0\xa0\
+\x10\0\0\x72\x02\0\0\x20\x10\0\0\x19\xd8\x01\0\xb8\x10\0\0\x72\x02\0\0\x4e\x10\
+\0\0\x27\xfc\x01\0\xd0\x10\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\xd8\x10\0\
+\0\x72\x02\0\0\xf7\x0f\0\0\x11\xe8\x01\0\x18\x11\0\0\x72\x02\0\0\x4e\x10\0\0\
+\x27\xfc\x01\0\x20\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\x28\x11\0\0\
+\x72\x02\0\0\xf7\x0f\0\0\x11\xe8\x01\0\x50\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x27\
+\xfc\x01\0\x70\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\x78\x11\0\0\x72\
+\x02\0\0\xf7\x0f\0\0\x11\xe8\x01\0\xa0\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\
+\x01\0\xc0\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\xc8\x11\0\0\x72\x02\0\
+\0\xf7\x0f\0\0\x11\xe8\x01\0\x08\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\
+\x10\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\x18\x12\0\0\x72\x02\0\0\xf7\
+\x0f\0\0\x11\xe8\x01\0\x58\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\x60\
+\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\x68\x12\0\0\x72\x02\0\0\xf7\x0f\
+\0\0\x11\xe8\x01\0\xa8\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\xb0\x12\0\
+\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\xb8\x12\0\0\x72\x02\0\0\xf7\x0f\0\0\
+\x11\xe8\x01\0\xe0\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\xe8\x12\0\0\
+\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\xf0\x12\0\0\x72\x02\0\0\x5a\x0f\0\0\x3d\
+\xd0\x01\0\0\x13\0\0\x72\x02\0\0\x5a\x0f\0\0\x05\xd0\x01\0\x10\x13\0\0\x72\x02\
+\0\0\x9a\x10\0\0\x2e\xa4\x08\0\x30\x13\0\0\x72\x02\0\0\x9a\x10\0\0\x24\xa4\x08\
+\0\x48\x13\0\0\x72\x02\0\0\x9a\x10\0\0\x13\xa4\x08\0\x58\x13\0\0\x72\x02\0\0\0\
+\0\0\0\0\0\0\0\x60\x13\0\0\x72\x02\0\0\xd9\x10\0\0\x15\xb0\x08\0\x78\x13\0\0\
+\x72\x02\0\0\x21\x11\0\0\x11\xbc\x08\0\x80\x13\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\
+\xa0\x13\0\0\x72\x02\0\0\x3a\x11\0\0\x01\xe0\x08\0\xa8\x13\0\0\x72\x02\0\0\x3c\
+\x11\0\0\x18\xc0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\x03\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x25\x01\0\0\0\0\x03\0\xa0\x13\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\x78\x01\0\0\0\0\x03\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\x4e\x01\0\0\0\0\x03\0\x80\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xbd\0\0\0\0\0\x03\
+\0\xd0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2a\x02\0\0\0\0\x03\0\x20\x02\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\xfc\0\0\0\0\0\x03\0\xe8\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x43\
+\x02\0\0\0\0\x03\0\x10\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1d\x01\0\0\0\0\x03\0\
+\xe0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1a\x02\0\0\0\0\x03\0\x30\x03\0\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\x12\x02\0\0\0\0\x03\0\x38\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd4\
+\0\0\0\0\0\x03\0\xf0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x0a\x02\0\0\0\0\x03\0\xf8\
+\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x3e\x01\0\0\0\0\x03\0\xe8\x0c\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\x57\x01\0\0\0\0\x03\0\xa0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd0\x01\
+\0\0\0\0\x03\0\x38\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7f\x01\0\0\0\0\x03\0\x78\
+\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x53\x02\0\0\0\0\x03\0\xb0\x0e\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\xe9\x01\0\0\0\0\x03\0\x50\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xc8\x01\
+\0\0\0\0\x03\0\xc0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb0\x01\0\0\0\0\x03\0\x60\
+\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x8f\x01\0\0\0\0\x03\0\x60\x08\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\x5f\x01\0\0\0\0\x03\0\x30\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x46\x01\
+\0\0\0\0\x03\0\x40\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xe1\x01\0\0\0\0\x03\0\xe8\
+\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xc0\x01\0\0\0\0\x03\0\x48\x08\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\x67\x01\0\0\0\0\x03\0\x18\x09\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x22\x02\
+\0\0\0\0\x03\0\x80\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb8\x01\0\0\0\0\x03\0\xf8\
+\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x87\x01\0\0\0\0\x03\0\x50\x0d\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\xe4\0\0\0\0\0\x03\0\x08\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x15\x01\0\
+\0\0\0\x03\0\xe8\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xdc\0\0\0\0\0\x03\0\xb0\x0a\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\x4b\x02\0\0\0\0\x03\0\xd8\x0a\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\xa8\x01\0\0\0\0\x03\0\x80\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x36\x01\0\0\0\
+\0\x03\0\xb0\x0b\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf4\0\0\0\0\0\x03\0\xc8\x0b\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\x3b\x02\0\0\0\0\x03\0\xf8\x0b\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\xd9\x01\0\0\0\0\x03\0\x18\x0c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x02\0\0\0\0\
+\x03\0\x10\x0c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xcc\0\0\0\0\0\x03\0\x18\x0d\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\xa0\x01\0\0\0\0\x03\0\xc0\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\x0d\x01\0\0\0\0\x03\0\xd0\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xc4\0\0\0\0\0\x03\0\
+\xe8\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xfa\x01\0\0\0\0\x03\0\x18\x0e\0\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\x2e\x01\0\0\0\0\x03\0\0\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xec\0\
+\0\0\0\0\x03\0\x18\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x32\x02\0\0\0\0\x03\0\xf8\
+\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf1\x01\0\0\0\0\x03\0\x30\x10\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\x97\x01\0\0\0\0\x03\0\x58\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x6f\x01\
+\0\0\0\0\x03\0\x10\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\x01\0\0\0\0\x03\0\xa8\
+\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x59\0\0\0\x12\0\x03\0\0\0\0\0\0\0\0\0\xb8\x13\
+\0\0\0\0\0\0\x3e\0\0\0\x11\0\x05\0\0\0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\
+\x11\0\x05\0\x20\0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x86\0\0\0\x11\0\x05\0\x40\0\0\
+\0\0\0\0\0\x20\0\0\0\0\0\0\0\x7d\0\0\0\x11\0\x06\0\0\0\0\0\0\0\0\0\x07\0\0\0\0\
+\0\0\0\x28\0\0\0\0\0\0\0\x01\0\0\0\x36\0\0\0\x50\0\0\0\0\0\0\0\x01\0\0\0\x37\0\
+\0\0\x60\x13\0\0\0\0\0\0\x01\0\0\0\x38\0\0\0\x18\x05\0\0\0\0\0\0\x04\0\0\0\x36\
+\0\0\0\x24\x05\0\0\0\0\0\0\x04\0\0\0\x37\0\0\0\x30\x05\0\0\0\0\0\0\x04\0\0\0\
+\x38\0\0\0\x48\x05\0\0\0\0\0\0\x04\0\0\0\x39\0\0\0\x2c\0\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\x40\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\0\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\x60\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\0\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\x80\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\0\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\xa0\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\0\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\xc0\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\0\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\xe0\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\0\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\0\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x01\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\x20\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x01\0\0\0\0\0\0\x04\0\0\
+\0\x01\0\0\0\x40\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x01\0\0\0\0\0\0\x04\0\
+\0\0\x01\0\0\0\x60\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x01\0\0\0\0\0\0\x04\
+\0\0\0\x01\0\0\0\x80\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x01\0\0\0\0\0\0\
+\x04\0\0\0\x01\0\0\0\xa0\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x01\0\0\0\0\0\
+\0\x04\0\0\0\x01\0\0\0\xc0\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x01\0\0\0\0\
+\0\0\x04\0\0\0\x01\0\0\0\xe0\x01\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x01\0\0\0\
+\0\0\0\x04\0\0\0\x01\0\0\0\0\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x02\0\0\0\
+\0\0\0\x04\0\0\0\x01\0\0\0\x20\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x02\0\0\
+\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x02\0\
+\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x02\
+\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\
+\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
+\xb0\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
+\0\xd0\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\
+\0\0\xf0\x02\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\
+\0\0\x10\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x03\0\0\0\0\0\0\x04\0\0\0\x01\
+\0\0\0\x30\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x03\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\x50\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x03\0\0\0\0\0\0\x04\0\0\
+\0\x01\0\0\0\x70\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x03\0\0\0\0\0\0\x04\0\
+\0\0\x01\0\0\0\x90\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x03\0\0\0\0\0\0\x04\
+\0\0\0\x01\0\0\0\xb0\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x03\0\0\0\0\0\0\
+\x04\0\0\0\x01\0\0\0\xd0\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x03\0\0\0\0\0\
+\0\x04\0\0\0\x01\0\0\0\xf0\x03\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x04\0\0\0\0\0\
+\0\x04\0\0\0\x01\0\0\0\x10\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x04\0\0\0\0\
+\0\0\x04\0\0\0\x01\0\0\0\x30\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x04\0\0\0\
+\0\0\0\x04\0\0\0\x01\0\0\0\x50\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x04\0\0\
+\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x04\0\
+\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x04\
+\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\
+\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
+\xe0\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x04\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
+\0\0\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
+\0\x20\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\
+\0\0\x40\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x05\0\0\0\0\0\0\x04\0\0\0\x01\
+\0\0\0\x60\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x05\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\x80\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x05\0\0\0\0\0\0\x04\0\0\
+\0\x01\0\0\0\xa0\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x05\0\0\0\0\0\0\x04\0\
+\0\0\x01\0\0\0\xc0\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x05\0\0\0\0\0\0\x04\
+\0\0\0\x01\0\0\0\xe0\x05\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x05\0\0\0\0\0\0\
+\x04\0\0\0\x01\0\0\0\0\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x06\0\0\0\0\0\0\
+\x04\0\0\0\x01\0\0\0\x20\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x06\0\0\0\0\0\
+\0\x04\0\0\0\x01\0\0\0\x40\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x06\0\0\0\0\
+\0\0\x04\0\0\0\x01\0\0\0\x60\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x06\0\0\0\
+\0\0\0\x04\0\0\0\x01\0\0\0\x80\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x06\0\0\
+\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x06\0\
+\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x06\
+\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\
+\x06\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\
+\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
+\x30\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
+\0\x50\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\
+\0\0\x70\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x07\0\0\0\0\0\0\x04\0\0\0\x01\
+\0\0\0\x90\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x07\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\xb0\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x07\0\0\0\0\0\0\x04\0\0\
+\0\x01\0\0\0\xd0\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x07\0\0\0\0\0\0\x04\0\
+\0\0\x01\0\0\0\xf0\x07\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x08\0\0\0\0\0\0\x04\0\
+\0\0\x01\0\0\0\x10\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x08\0\0\0\0\0\0\x04\
+\0\0\0\x01\0\0\0\x30\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x08\0\0\0\0\0\0\
+\x04\0\0\0\x01\0\0\0\x50\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x08\0\0\0\0\0\
+\0\x04\0\0\0\x01\0\0\0\x70\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x08\0\0\0\0\
+\0\0\x04\0\0\0\x01\0\0\0\x90\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x08\0\0\0\
+\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x08\0\0\
+\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x08\0\
+\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x08\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x09\0\
+\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x09\
+\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\
+\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
+\x60\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
+\0\x80\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\
+\0\0\xa0\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x09\0\0\0\0\0\0\x04\0\0\0\x01\
+\0\0\0\xc0\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x09\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\xe0\x09\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x09\0\0\0\0\0\0\x04\0\0\
+\0\x01\0\0\0\0\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x0a\0\0\0\0\0\0\x04\0\0\
+\0\x01\0\0\0\x20\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x0a\0\0\0\0\0\0\x04\0\
+\0\0\x01\0\0\0\x40\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x0a\0\0\0\0\0\0\x04\
+\0\0\0\x01\0\0\0\x60\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\x0a\0\0\0\0\0\0\
+\x04\0\0\0\x01\0\0\0\x80\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\x0a\0\0\0\0\0\
+\0\x04\0\0\0\x01\0\0\0\xa0\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xb0\x0a\0\0\0\0\
+\0\0\x04\0\0\0\x01\0\0\0\xc0\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xd0\x0a\0\0\0\
+\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x0a\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xf0\x0a\0\0\
+\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x10\x0b\0\0\
+\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x30\x0b\0\
+\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\x0b\
+\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\
+\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\
+\x90\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\
+\0\xb0\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xc0\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\
+\0\0\xd0\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xe0\x0b\0\0\0\0\0\0\x04\0\0\0\x01\
+\0\0\0\xf0\x0b\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\0\x0c\0\0\0\0\0\0\x04\0\0\0\x01\
+\0\0\0\x10\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x20\x0c\0\0\0\0\0\0\x04\0\0\0\
+\x01\0\0\0\x30\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x40\x0c\0\0\0\0\0\0\x04\0\0\
+\0\x01\0\0\0\x50\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x0c\0\0\0\0\0\0\x04\0\
+\0\0\x01\0\0\0\x70\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x0c\0\0\0\0\0\0\x04\
+\0\0\0\x01\0\0\0\x90\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x0c\0\0\0\0\0\0\
+\x04\0\0\0\x01\0\0\0\xb0\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x3f\x40\x41\x42\
+\x43\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x74\x6f\x65\x70\x6c\x69\
+\x74\x7a\x5f\x6b\x65\x79\0\x2e\x74\x65\x78\x74\0\x2e\x72\x65\x6c\x2e\x42\x54\
+\x46\x2e\x65\x78\x74\0\x2e\x72\x65\x6c\x73\x6f\x63\x6b\x65\x74\0\x2e\x6d\x61\
+\x70\x73\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x63\x6f\x6e\x66\x69\
+\x67\x75\x72\x61\x74\x69\x6f\x6e\x73\0\x74\x75\x6e\x5f\x72\x73\x73\x5f\x73\x74\
+\x65\x65\x72\x69\x6e\x67\x5f\x70\x72\x6f\x67\0\x2e\x6c\x6c\x76\x6d\x5f\x61\x64\
+\x64\x72\x73\x69\x67\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x74\x61\x70\x5f\x72\
+\x73\x73\x5f\x6d\x61\x70\x5f\x69\x6e\x64\x69\x72\x65\x63\x74\x69\x6f\x6e\x5f\
+\x74\x61\x62\x6c\x65\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\
+\x62\0\x2e\x72\x65\x6c\x2e\x42\x54\x46\0\x4c\x42\x42\x30\x5f\x39\0\x4c\x42\x42\
+\x30\x5f\x38\x39\0\x4c\x42\x42\x30\x5f\x36\x39\0\x4c\x42\x42\x30\x5f\x35\x39\0\
+\x4c\x42\x42\x30\x5f\x34\x39\0\x4c\x42\x42\x30\x5f\x33\x39\0\x4c\x42\x42\x30\
+\x5f\x39\x38\0\x4c\x42\x42\x30\x5f\x37\x38\0\x4c\x42\x42\x30\x5f\x31\x38\0\x4c\
+\x42\x42\x30\x5f\x31\x30\x38\0\x4c\x42\x42\x30\x5f\x38\x37\0\x4c\x42\x42\x30\
+\x5f\x34\x37\0\x4c\x42\x42\x30\x5f\x31\x37\0\x4c\x42\x42\x30\x5f\x31\x30\x37\0\
+\x4c\x42\x42\x30\x5f\x39\x36\0\x4c\x42\x42\x30\x5f\x37\x36\0\x4c\x42\x42\x30\
+\x5f\x36\x36\0\x4c\x42\x42\x30\x5f\x34\x36\0\x4c\x42\x42\x30\x5f\x31\x30\x36\0\
+\x4c\x42\x42\x30\x5f\x36\x35\0\x4c\x42\x42\x30\x5f\x34\x35\0\x4c\x42\x42\x30\
+\x5f\x33\x35\0\x4c\x42\x42\x30\x5f\x31\x30\x35\0\x4c\x42\x42\x30\x5f\x34\0\x4c\
+\x42\x42\x30\x5f\x35\x34\0\x4c\x42\x42\x30\x5f\x34\x34\0\x4c\x42\x42\x30\x5f\
+\x33\x34\0\x4c\x42\x42\x30\x5f\x31\x30\x34\0\x4c\x42\x42\x30\x5f\x39\x33\0\x4c\
+\x42\x42\x30\x5f\x38\x33\0\x4c\x42\x42\x30\x5f\x35\x33\0\x4c\x42\x42\x30\x5f\
+\x34\x33\0\x4c\x42\x42\x30\x5f\x33\x33\0\x4c\x42\x42\x30\x5f\x32\x33\0\x4c\x42\
+\x42\x30\x5f\x31\x30\x33\0\x4c\x42\x42\x30\x5f\x38\x32\0\x4c\x42\x42\x30\x5f\
+\x35\x32\0\x4c\x42\x42\x30\x5f\x32\x32\0\x4c\x42\x42\x30\x5f\x31\x30\x32\0\x4c\
+\x42\x42\x30\x5f\x39\x31\0\x4c\x42\x42\x30\x5f\x38\x31\0\x4c\x42\x42\x30\x5f\
+\x37\x31\0\x4c\x42\x42\x30\x5f\x36\x31\0\x4c\x42\x42\x30\x5f\x35\x31\0\x4c\x42\
+\x42\x30\x5f\x34\x31\0\x4c\x42\x42\x30\x5f\x31\x31\0\x4c\x42\x42\x30\x5f\x31\
+\x30\x31\0\x4c\x42\x42\x30\x5f\x38\x30\0\x4c\x42\x42\x30\x5f\x36\x30\0\x4c\x42\
+\x42\x30\x5f\x35\x30\0\x4c\x42\x42\x30\x5f\x32\x30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xae\0\0\0\x03\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x25\x4a\0\0\0\0\0\0\x6d\x02\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1a\0\0\0\x01\0\0\0\x06\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\x40\0\0\0\0\0\0\0\xe0\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\x64\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\x3d\0\0\
-\0\0\0\0\x30\0\0\0\0\0\0\0\x0c\0\0\0\x03\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\
-\0\0\x2d\0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x20\x14\0\0\0\0\0\0\
-\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x88\0\0\0\
-\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x80\x14\0\0\0\0\0\0\x07\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xc2\0\0\0\x01\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x88\x14\0\0\0\0\0\0\x8d\x16\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xbe\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\x70\x3d\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\x0c\0\0\0\x07\0\0\0\x08\
-\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x24\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\x18\x2b\0\0\0\0\0\0\xa0\x0c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\x20\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb0\
-\x3d\0\0\0\0\0\0\x70\x0c\0\0\0\0\0\0\x0c\0\0\0\x09\0\0\0\x08\0\0\0\0\0\0\0\x10\
-\0\0\0\0\0\0\0\x79\0\0\0\x03\x4c\xff\x6f\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\x20\
-\x4a\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\xb6\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb8\x37\0\0\0\0\0\0\
-\x88\x05\0\0\0\0\0\0\x01\0\0\0\x36\0\0\0\x08\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0";
+\0\0\0\0\0\0\0\0\0\0\0\0\xa4\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\x8d\x4a\0\0\0\0\0\0\x5b\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\x1a\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x31\0\
+\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\xb8\x13\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2d\0\0\0\x09\0\0\0\
+\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x88\x3d\0\0\0\0\0\0\x30\0\0\0\0\0\0\0\x0c\0\
+\0\0\x03\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x38\0\0\0\x01\0\0\0\x03\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\xf8\x13\0\0\0\0\0\0\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7e\0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\x58\x14\0\0\0\0\0\0\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\xb8\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x60\
+\x14\0\0\0\0\0\0\xf6\x16\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\0\xb4\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb8\x3d\0\0\0\0\
+\0\0\x40\0\0\0\0\0\0\0\x0c\0\0\0\x07\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\
+\x24\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x58\x2b\0\0\0\0\0\0\xc0\
+\x0c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x20\0\0\0\
+\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf8\x3d\0\0\0\0\0\0\x90\x0c\0\0\0\
+\0\0\0\x0c\0\0\0\x09\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x6f\0\0\0\x03\
+\x4c\xff\x6f\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\x88\x4a\0\0\0\0\0\0\x05\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xac\0\0\0\x02\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x18\x38\0\0\0\0\0\0\x70\x05\0\0\0\0\0\0\x01\0\0\
+\0\x35\0\0\0\x08\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0";
 }
 
 #ifdef __cplusplus
diff --git a/ebpf/ebpf_rss.c b/ebpf/ebpf_rss.c
index cee658c158..3978333584 100644
--- a/ebpf/ebpf_rss.c
+++ b/ebpf/ebpf_rss.c
@@ -49,8 +49,6 @@ bool ebpf_rss_load(struct EBPFRSSContext *ctx)
         goto error;
     }
 
-    bpf_program__set_type(rss_bpf_ctx->progs.tun_rss_steering_prog, BPF_PROG_TYPE_SOCKET_FILTER);
-
     if (rss_bpf__load(rss_bpf_ctx)) {
         trace_ebpf_error("eBPF RSS", "can not load RSS program");
         goto error;
diff --git a/tools/ebpf/rss.bpf.c b/tools/ebpf/rss.bpf.c
index 667ea6899e..9ec4bd2d91 100644
--- a/tools/ebpf/rss.bpf.c
+++ b/tools/ebpf/rss.bpf.c
@@ -531,7 +531,7 @@ static inline bool calculate_rss_hash(struct __sk_buff *skb,
     return true;
 }
 
-SEC("tun_rss_steering")
+SEC("socket")
 int tun_rss_steering_prog(struct __sk_buff *skb)
 {
 
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 18/21] ebpf: Simplify error handling
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (16 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 17/21] ebpf: Use standard section name Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 19/21] ebpf: Return 0 when configuration fails Akihiko Odaki
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

The error handling procedures required when rss_bpf__open() and
rss_bpf__load(rss_bpf_ctx) are different so it's better to implement
them separately.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 ebpf/ebpf_rss.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/ebpf/ebpf_rss.c b/ebpf/ebpf_rss.c
index 3978333584..2de9e7851f 100644
--- a/ebpf/ebpf_rss.c
+++ b/ebpf/ebpf_rss.c
@@ -46,12 +46,13 @@ bool ebpf_rss_load(struct EBPFRSSContext *ctx)
     rss_bpf_ctx = rss_bpf__open();
     if (rss_bpf_ctx == NULL) {
         trace_ebpf_error("eBPF RSS", "can not open eBPF RSS object");
-        goto error;
+        return false;
     }
 
     if (rss_bpf__load(rss_bpf_ctx)) {
         trace_ebpf_error("eBPF RSS", "can not load RSS program");
-        goto error;
+        rss_bpf__destroy(rss_bpf_ctx);
+        return false;
     }
 
     ctx->obj = rss_bpf_ctx;
@@ -65,11 +66,6 @@ bool ebpf_rss_load(struct EBPFRSSContext *ctx)
             rss_bpf_ctx->maps.tap_rss_map_toeplitz_key);
 
     return true;
-error:
-    rss_bpf__destroy(rss_bpf_ctx);
-    ctx->obj = NULL;
-
-    return false;
 }
 
 static bool ebpf_rss_set_config(struct EBPFRSSContext *ctx,
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 19/21] ebpf: Return 0 when configuration fails
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (17 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 18/21] ebpf: Simplify error handling Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 20/21] ebpf: Refactor tun_rss_steering_prog() Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 21/21] ebpf: Add a separate target for skeleton Akihiko Odaki
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

The kernel interprets the returned value as an unsigned 32-bit so -1
will mean queue 4294967295, which is awkward. Return 0 instead.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 ebpf/rss.bpf.skeleton.h | 1339 +++++++++++++++++++--------------------
 tools/ebpf/rss.bpf.c    |    2 +-
 2 files changed, 670 insertions(+), 671 deletions(-)

diff --git a/ebpf/rss.bpf.skeleton.h b/ebpf/rss.bpf.skeleton.h
index f011c3258e..3e33786799 100644
--- a/ebpf/rss.bpf.skeleton.h
+++ b/ebpf/rss.bpf.skeleton.h
@@ -176,643 +176,642 @@ err:
 
 static inline const void *rss_bpf__elf_bytes(size_t *sz)
 {
-	*sz = 20520;
+	*sz = 20480;
 	return (const void *)"\
 \x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\xe8\x4c\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0d\0\
-\x01\0\xbf\x19\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\x4c\xff\0\0\0\0\xbf\xa7\
-\0\0\0\0\0\0\x07\x07\0\0\x4c\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\xbf\x72\0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\xbf\x06\0\0\0\0\0\0\x18\x01\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\xbf\x72\0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\xbf\x08\0\0\0\0\0\0\
-\x18\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\x15\x06\x62\x02\0\0\0\0\xbf\x87\0\0\
-\0\0\0\0\x15\x07\x60\x02\0\0\0\0\x71\x61\0\0\0\0\0\0\x55\x01\x01\0\0\0\0\0\x05\
-\0\x59\x02\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xc0\xff\0\0\0\0\x7b\x1a\xb8\xff\
-\0\0\0\0\x7b\x1a\xb0\xff\0\0\0\0\x7b\x1a\xa8\xff\0\0\0\0\x7b\x1a\xa0\xff\0\0\0\
-\0\x63\x1a\x98\xff\0\0\0\0\x7b\x1a\x90\xff\0\0\0\0\x7b\x1a\x88\xff\0\0\0\0\x7b\
-\x1a\x80\xff\0\0\0\0\x7b\x1a\x78\xff\0\0\0\0\x7b\x1a\x70\xff\0\0\0\0\x7b\x1a\
-\x68\xff\0\0\0\0\x7b\x1a\x60\xff\0\0\0\0\x7b\x1a\x58\xff\0\0\0\0\x7b\x1a\x50\
-\xff\0\0\0\0\x15\x09\x48\x02\0\0\0\0\x6b\x1a\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\
-\0\x07\x03\0\0\xc8\xff\xff\xff\xbf\x91\0\0\0\0\0\0\xb7\x02\0\0\x0c\0\0\0\xb7\
-\x04\0\0\x02\0\0\0\xb7\x05\0\0\0\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\
-\x77\0\0\0\x20\0\0\0\x55\0\x3d\x02\0\0\0\0\xb7\x02\0\0\x10\0\0\0\x69\xa1\xc8\
-\xff\0\0\0\0\xbf\x13\0\0\0\0\0\0\xdc\x03\0\0\x10\0\0\0\x15\x03\x02\0\0\x81\0\0\
-\x55\x03\x0b\0\xa8\x88\0\0\xb7\x02\0\0\x14\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\
-\0\xc8\xff\xff\xff\xbf\x91\0\0\0\0\0\0\xb7\x04\0\0\x02\0\0\0\xb7\x05\0\0\0\0\0\
-\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x55\0\x2d\x02\0\
-\0\0\0\x69\xa1\xc8\xff\0\0\0\0\x15\x01\x2b\x02\0\0\0\0\x7b\x7a\x30\xff\0\0\0\0\
-\x7b\x9a\x38\xff\0\0\0\0\x15\x01\x55\0\x86\xdd\0\0\x55\x01\x39\0\x08\0\0\0\xb7\
-\x07\0\0\x01\0\0\0\x73\x7a\x50\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xd8\xff\
-\0\0\0\0\x7b\x1a\xd0\xff\0\0\0\0\x7b\x1a\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\
-\x07\x03\0\0\xc8\xff\xff\xff\x79\xa1\x38\xff\0\0\0\0\xb7\x02\0\0\0\0\0\0\xb7\
-\x04\0\0\x14\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\
-\0\x77\0\0\0\x20\0\0\0\x55\0\x17\x02\0\0\0\0\x69\xa1\xce\xff\0\0\0\0\x55\x01\
-\x01\0\0\0\0\0\xb7\x07\0\0\0\0\0\0\x61\xa1\xd4\xff\0\0\0\0\x63\x1a\x5c\xff\0\0\
-\0\0\x61\xa1\xd8\xff\0\0\0\0\x63\x1a\x60\xff\0\0\0\0\x71\xa9\xd1\xff\0\0\0\0\
-\x73\x7a\x56\xff\0\0\0\0\x71\xa1\xc8\xff\0\0\0\0\x67\x01\0\0\x02\0\0\0\x57\x01\
-\0\0\x3c\0\0\0\x7b\x1a\x40\xff\0\0\0\0\xbf\x91\0\0\0\0\0\0\x57\x01\0\0\xff\0\0\
-\0\x15\x01\x19\0\0\0\0\0\x57\x07\0\0\xff\0\0\0\x55\x07\x17\0\0\0\0\0\x57\x09\0\
-\0\xff\0\0\0\x15\x09\x5a\x01\x11\0\0\0\x55\x09\x14\0\x06\0\0\0\xb7\x01\0\0\x01\
-\0\0\0\x73\x1a\x53\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xd8\xff\0\0\0\0\x7b\
-\x1a\xd0\xff\0\0\0\0\x7b\x1a\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\
-\xc8\xff\xff\xff\x79\xa1\x38\xff\0\0\0\0\x79\xa2\x40\xff\0\0\0\0\xb7\x04\0\0\
-\x14\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\
-\0\0\x20\0\0\0\x55\0\xf2\x01\0\0\0\0\x69\xa1\xc8\xff\0\0\0\0\x6b\x1a\x58\xff\0\
-\0\0\0\x69\xa1\xca\xff\0\0\0\0\x6b\x1a\x5a\xff\0\0\0\0\x71\xa1\x50\xff\0\0\0\0\
-\x15\x01\xdb\0\0\0\0\0\x71\x62\x03\0\0\0\0\0\x67\x02\0\0\x08\0\0\0\x71\x61\x02\
-\0\0\0\0\0\x4f\x12\0\0\0\0\0\0\x71\x63\x04\0\0\0\0\0\x67\x03\0\0\x10\0\0\0\x71\
-\x61\x05\0\0\0\0\0\x67\x01\0\0\x18\0\0\0\x4f\x31\0\0\0\0\0\0\x4f\x21\0\0\0\0\0\
-\0\x71\xa2\x53\xff\0\0\0\0\x79\xa0\x30\xff\0\0\0\0\x15\x02\x0c\x01\0\0\0\0\xbf\
-\x12\0\0\0\0\0\0\x57\x02\0\0\x02\0\0\0\x15\x02\x09\x01\0\0\0\0\x61\xa1\x5c\xff\
-\0\0\0\0\x63\x1a\xa0\xff\0\0\0\0\x61\xa1\x60\xff\0\0\0\0\x63\x1a\xa4\xff\0\0\0\
-\0\x69\xa1\x58\xff\0\0\0\0\x6b\x1a\xa8\xff\0\0\0\0\x69\xa1\x5a\xff\0\0\0\0\x6b\
-\x1a\xaa\xff\0\0\0\0\x05\0\x6a\x01\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x51\
-\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x7b\x1a\xe8\xff\0\0\0\0\x7b\x1a\xe0\xff\0\0\0\
-\0\x7b\x1a\xd8\xff\0\0\0\0\x7b\x1a\xd0\xff\0\0\0\0\x7b\x1a\xc8\xff\0\0\0\0\xbf\
-\xa3\0\0\0\0\0\0\x07\x03\0\0\xc8\xff\xff\xff\xb7\x01\0\0\x28\0\0\0\x7b\x1a\x40\
-\xff\0\0\0\0\xbf\x91\0\0\0\0\0\0\xb7\x02\0\0\0\0\0\0\xb7\x04\0\0\x28\0\0\0\xb7\
-\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\
-\x55\0\xfe\0\0\0\0\0\x79\xa1\xd8\xff\0\0\0\0\x63\x1a\x64\xff\0\0\0\0\x77\x01\0\
-\0\x20\0\0\0\x63\x1a\x68\xff\0\0\0\0\x79\xa1\xd0\xff\0\0\0\0\x63\x1a\x5c\xff\0\
-\0\0\0\x77\x01\0\0\x20\0\0\0\x63\x1a\x60\xff\0\0\0\0\x79\xa1\xe0\xff\0\0\0\0\
-\x63\x1a\x6c\xff\0\0\0\0\x77\x01\0\0\x20\0\0\0\x63\x1a\x70\xff\0\0\0\0\x79\xa1\
-\xe8\xff\0\0\0\0\x63\x1a\x74\xff\0\0\0\0\x77\x01\0\0\x20\0\0\0\x63\x1a\x78\xff\
-\0\0\0\0\x71\xa9\xce\xff\0\0\0\0\x25\x09\x13\x01\x3c\0\0\0\xb7\x01\0\0\x01\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\xc0\x4c\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0d\0\
+\x01\0\x7b\x1a\x40\xff\0\0\0\0\xb7\x09\0\0\0\0\0\0\x63\x9a\x4c\xff\0\0\0\0\xbf\
+\xa7\0\0\0\0\0\0\x07\x07\0\0\x4c\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\xbf\x72\0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\xbf\x06\0\0\0\0\0\0\x18\x01\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\xbf\x72\0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\xbf\x08\0\0\0\0\0\
+\0\x15\x06\x61\x02\0\0\0\0\xbf\x87\0\0\0\0\0\0\x15\x07\x5f\x02\0\0\0\0\x71\x61\
+\0\0\0\0\0\0\x55\x01\x01\0\0\0\0\0\x05\0\x58\x02\0\0\0\0\xb7\x01\0\0\0\0\0\0\
+\x63\x1a\xc0\xff\0\0\0\0\x7b\x1a\xb8\xff\0\0\0\0\x7b\x1a\xb0\xff\0\0\0\0\x7b\
+\x1a\xa8\xff\0\0\0\0\x7b\x1a\xa0\xff\0\0\0\0\x63\x1a\x98\xff\0\0\0\0\x7b\x1a\
+\x90\xff\0\0\0\0\x7b\x1a\x88\xff\0\0\0\0\x7b\x1a\x80\xff\0\0\0\0\x7b\x1a\x78\
+\xff\0\0\0\0\x7b\x1a\x70\xff\0\0\0\0\x7b\x1a\x68\xff\0\0\0\0\x7b\x1a\x60\xff\0\
+\0\0\0\x7b\x1a\x58\xff\0\0\0\0\x7b\x1a\x50\xff\0\0\0\0\x79\xa9\x40\xff\0\0\0\0\
+\x15\x09\x46\x02\0\0\0\0\x6b\x1a\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\
+\0\xc8\xff\xff\xff\xbf\x91\0\0\0\0\0\0\xb7\x02\0\0\x0c\0\0\0\xb7\x04\0\0\x02\0\
+\0\0\xb7\x05\0\0\0\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\
+\0\0\0\x55\0\x3b\x02\0\0\0\0\xb7\x02\0\0\x10\0\0\0\x69\xa1\xc8\xff\0\0\0\0\xbf\
+\x13\0\0\0\0\0\0\xdc\x03\0\0\x10\0\0\0\x15\x03\x02\0\0\x81\0\0\x55\x03\x0b\0\
+\xa8\x88\0\0\xb7\x02\0\0\x14\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\xc8\xff\xff\
+\xff\xbf\x91\0\0\0\0\0\0\xb7\x04\0\0\x02\0\0\0\xb7\x05\0\0\0\0\0\0\x85\0\0\0\
+\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x55\0\x2b\x02\0\0\0\0\x69\
+\xa1\xc8\xff\0\0\0\0\x15\x01\x29\x02\0\0\0\0\x15\x01\x56\0\x86\xdd\0\0\x7b\x7a\
+\x30\xff\0\0\0\0\x55\x01\x39\0\x08\0\0\0\xb7\x07\0\0\x01\0\0\0\x73\x7a\x50\xff\
+\0\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xd8\xff\0\0\0\0\x7b\x1a\xd0\xff\0\0\0\0\
+\x7b\x1a\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\xc8\xff\xff\xff\x79\
+\xa1\x40\xff\0\0\0\0\xb7\x02\0\0\0\0\0\0\xb7\x04\0\0\x14\0\0\0\xb7\x05\0\0\x01\
+\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x55\0\x16\
+\x02\0\0\0\0\x69\xa1\xce\xff\0\0\0\0\x55\x01\x01\0\0\0\0\0\xb7\x07\0\0\0\0\0\0\
+\x61\xa1\xd4\xff\0\0\0\0\x63\x1a\x5c\xff\0\0\0\0\x61\xa1\xd8\xff\0\0\0\0\x63\
+\x1a\x60\xff\0\0\0\0\x71\xa9\xd1\xff\0\0\0\0\x73\x7a\x56\xff\0\0\0\0\x71\xa1\
+\xc8\xff\0\0\0\0\x67\x01\0\0\x02\0\0\0\x57\x01\0\0\x3c\0\0\0\x7b\x1a\x38\xff\0\
+\0\0\0\xbf\x91\0\0\0\0\0\0\x57\x01\0\0\xff\0\0\0\x15\x01\x19\0\0\0\0\0\x57\x07\
+\0\0\xff\0\0\0\x55\x07\x17\0\0\0\0\0\x57\x09\0\0\xff\0\0\0\x15\x09\x59\x01\x11\
+\0\0\0\x55\x09\x14\0\x06\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x53\xff\0\0\0\0\
+\xb7\x01\0\0\0\0\0\0\x63\x1a\xd8\xff\0\0\0\0\x7b\x1a\xd0\xff\0\0\0\0\x7b\x1a\
+\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\xc8\xff\xff\xff\x79\xa1\x40\
+\xff\0\0\0\0\x79\xa2\x38\xff\0\0\0\0\xb7\x04\0\0\x14\0\0\0\xb7\x05\0\0\x01\0\0\
+\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x55\0\xf1\x01\0\
+\0\0\0\x69\xa1\xc8\xff\0\0\0\0\x6b\x1a\x58\xff\0\0\0\0\x69\xa1\xca\xff\0\0\0\0\
+\x6b\x1a\x5a\xff\0\0\0\0\x71\xa1\x50\xff\0\0\0\0\x15\x01\xd9\0\0\0\0\0\x71\x62\
+\x03\0\0\0\0\0\x67\x02\0\0\x08\0\0\0\x71\x61\x02\0\0\0\0\0\x4f\x12\0\0\0\0\0\0\
+\x71\x63\x04\0\0\0\0\0\x67\x03\0\0\x10\0\0\0\x71\x61\x05\0\0\0\0\0\x67\x01\0\0\
+\x18\0\0\0\x4f\x31\0\0\0\0\0\0\x4f\x21\0\0\0\0\0\0\x71\xa2\x53\xff\0\0\0\0\x79\
+\xa0\x30\xff\0\0\0\0\x15\x02\x0a\x01\0\0\0\0\xbf\x12\0\0\0\0\0\0\x57\x02\0\0\
+\x02\0\0\0\x15\x02\x07\x01\0\0\0\0\x61\xa1\x5c\xff\0\0\0\0\x63\x1a\xa0\xff\0\0\
+\0\0\x61\xa1\x60\xff\0\0\0\0\x63\x1a\xa4\xff\0\0\0\0\x69\xa1\x58\xff\0\0\0\0\
+\x6b\x1a\xa8\xff\0\0\0\0\x69\xa1\x5a\xff\0\0\0\0\x6b\x1a\xaa\xff\0\0\0\0\x05\0\
+\x69\x01\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x51\xff\0\0\0\0\xb7\x01\0\0\0\0\
+\0\0\x7b\x1a\xe8\xff\0\0\0\0\x7b\x1a\xe0\xff\0\0\0\0\x7b\x1a\xd8\xff\0\0\0\0\
+\x7b\x1a\xd0\xff\0\0\0\0\x7b\x1a\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\
+\0\xc8\xff\xff\xff\xb7\x01\0\0\x28\0\0\0\x7b\x1a\x38\xff\0\0\0\0\xbf\x91\0\0\0\
+\0\0\0\xb7\x02\0\0\0\0\0\0\xb7\x04\0\0\x28\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\
+\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x55\0\xfd\0\0\0\0\0\x79\
+\xa1\xd8\xff\0\0\0\0\x63\x1a\x64\xff\0\0\0\0\x77\x01\0\0\x20\0\0\0\x63\x1a\x68\
+\xff\0\0\0\0\x79\xa1\xd0\xff\0\0\0\0\x63\x1a\x5c\xff\0\0\0\0\x77\x01\0\0\x20\0\
+\0\0\x63\x1a\x60\xff\0\0\0\0\x79\xa1\xe0\xff\0\0\0\0\x63\x1a\x6c\xff\0\0\0\0\
+\x77\x01\0\0\x20\0\0\0\x63\x1a\x70\xff\0\0\0\0\x79\xa1\xe8\xff\0\0\0\0\x63\x1a\
+\x74\xff\0\0\0\0\x77\x01\0\0\x20\0\0\0\x63\x1a\x78\xff\0\0\0\0\x71\xa9\xce\xff\
+\0\0\0\0\x7b\x7a\x30\xff\0\0\0\0\x25\x09\x11\x01\x3c\0\0\0\xb7\x01\0\0\x01\0\0\
 \0\x6f\x91\0\0\0\0\0\0\x18\x02\0\0\x01\0\0\0\0\0\0\0\0\x18\0\x1c\x5f\x21\0\0\0\
-\0\0\0\x55\x01\x01\0\0\0\0\0\x05\0\x0c\x01\0\0\0\0\xb7\x01\0\0\0\0\0\0\x6b\x1a\
-\xf8\xff\0\0\0\0\xb7\x01\0\0\x28\0\0\0\x7b\x1a\x40\xff\0\0\0\0\xbf\xa1\0\0\0\0\
+\0\0\0\x55\x01\x01\0\0\0\0\0\x05\0\x0a\x01\0\0\0\0\xb7\x01\0\0\0\0\0\0\x6b\x1a\
+\xf8\xff\0\0\0\0\xb7\x01\0\0\x28\0\0\0\x7b\x1a\x38\xff\0\0\0\0\xbf\xa1\0\0\0\0\
 \0\0\x07\x01\0\0\x8c\xff\xff\xff\x7b\x1a\x18\xff\0\0\0\0\xbf\xa1\0\0\0\0\0\0\
-\x07\x01\0\0\x7c\xff\xff\xff\x7b\x1a\x10\xff\0\0\0\0\x18\x07\0\0\x01\0\0\0\0\0\
-\0\0\0\x18\0\x1c\xb7\x02\0\0\0\0\0\0\x7b\x8a\x20\xff\0\0\0\0\x7b\x2a\x28\xff\0\
-\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\xf8\xff\xff\xff\x79\xa1\x38\xff\0\0\0\0\
-\x79\xa2\x40\xff\0\0\0\0\xb7\x04\0\0\x02\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\
-\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\
-\x01\xc8\0\0\0\0\0\xbf\x91\0\0\0\0\0\0\x15\x01\x26\0\x3c\0\0\0\x15\x01\x5f\0\
-\x2c\0\0\0\x55\x01\x60\0\x2b\0\0\0\xb7\x01\0\0\0\0\0\0\x63\x1a\xf0\xff\0\0\0\0\
-\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\xf0\xff\xff\xff\x79\xa7\x38\xff\0\0\0\0\xbf\
-\x71\0\0\0\0\0\0\x79\xa2\x40\xff\0\0\0\0\xb7\x04\0\0\x04\0\0\0\xb7\x05\0\0\x01\
-\0\0\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\
-\0\x20\0\0\0\x55\x01\x07\x01\0\0\0\0\x71\xa1\xf2\xff\0\0\0\0\x55\x01\x11\0\x02\
-\0\0\0\x71\xa1\xf1\xff\0\0\0\0\x55\x01\x0f\0\x02\0\0\0\x71\xa1\xf3\xff\0\0\0\0\
-\x55\x01\x0d\0\x01\0\0\0\x79\xa2\x40\xff\0\0\0\0\x07\x02\0\0\x08\0\0\0\xbf\x71\
-\0\0\0\0\0\0\x79\xa3\x18\xff\0\0\0\0\xb7\x04\0\0\x10\0\0\0\xb7\x05\0\0\x01\0\0\
-\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\
-\x20\0\0\0\x55\x01\xf6\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x55\xff\0\0\0\0\
-\x18\x07\0\0\x01\0\0\0\0\0\0\0\0\x18\0\x1c\x05\0\x3c\0\0\0\0\0\xb7\x08\0\0\x02\
-\0\0\0\xb7\x07\0\0\0\0\0\0\x6b\x7a\xf0\xff\0\0\0\0\x05\0\x13\0\0\0\0\0\x0f\x81\
-\0\0\0\0\0\0\xbf\x12\0\0\0\0\0\0\x07\x02\0\0\x01\0\0\0\x71\xa3\xf9\xff\0\0\0\0\
-\x67\x03\0\0\x03\0\0\0\x3d\x32\x09\0\0\0\0\0\xbf\x72\0\0\0\0\0\0\x07\x02\0\0\
-\x01\0\0\0\x67\x07\0\0\x20\0\0\0\xbf\x73\0\0\0\0\0\0\x77\x03\0\0\x20\0\0\0\xbf\
-\x27\0\0\0\0\0\0\xbf\x18\0\0\0\0\0\0\xb7\x01\0\0\x1d\0\0\0\x2d\x31\x04\0\0\0\0\
-\0\x79\xa8\x20\xff\0\0\0\0\x18\x07\0\0\x01\0\0\0\0\0\0\0\0\x18\0\x1c\x05\0\x25\
-\0\0\0\0\0\xbf\x89\0\0\0\0\0\0\x79\xa1\x40\xff\0\0\0\0\x0f\x19\0\0\0\0\0\0\xbf\
-\xa3\0\0\0\0\0\0\x07\x03\0\0\xf0\xff\xff\xff\x79\xa1\x38\xff\0\0\0\0\xbf\x92\0\
-\0\0\0\0\0\xb7\x04\0\0\x02\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\xbf\
-\x01\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\x79\0\0\0\
-\0\0\x71\xa2\xf0\xff\0\0\0\0\x55\x02\x0e\0\xc9\0\0\0\x07\x09\0\0\x02\0\0\0\x79\
-\xa1\x38\xff\0\0\0\0\xbf\x92\0\0\0\0\0\0\x79\xa3\x10\xff\0\0\0\0\xb7\x04\0\0\
-\x10\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\
-\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\x6c\0\0\0\0\0\xb7\x01\0\0\x01\
-\0\0\0\x73\x1a\x54\xff\0\0\0\0\x05\0\xde\xff\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\
-\x02\xcd\xff\0\0\0\0\x71\xa1\xf1\xff\0\0\0\0\x07\x01\0\0\x02\0\0\0\x05\0\xca\
-\xff\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x56\xff\0\0\0\0\x71\xa1\xf9\xff\0\0\
-\0\0\x67\x01\0\0\x03\0\0\0\x79\xa2\x40\xff\0\0\0\0\x0f\x12\0\0\0\0\0\0\x07\x02\
-\0\0\x08\0\0\0\x7b\x2a\x40\xff\0\0\0\0\x71\xa9\xf8\xff\0\0\0\0\x79\xa2\x28\xff\
-\0\0\0\0\x25\x09\x0c\0\x3c\0\0\0\xb7\x01\0\0\x01\0\0\0\x6f\x91\0\0\0\0\0\0\x5f\
-\x71\0\0\0\0\0\0\x55\x01\x01\0\0\0\0\0\x05\0\x07\0\0\0\0\0\x07\x02\0\0\x01\0\0\
-\0\xbf\x21\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\x7d\
-\xff\x0b\0\0\0\x71\xa7\x56\xff\0\0\0\0\x05\0\x09\xff\0\0\0\0\x15\x09\xf8\xff\
-\x87\0\0\0\x05\0\xfc\xff\0\0\0\0\x71\xa1\x51\xff\0\0\0\0\x79\xa0\x30\xff\0\0\0\
-\0\x15\x01\x0e\x01\0\0\0\0\x71\x62\x03\0\0\0\0\0\x67\x02\0\0\x08\0\0\0\x71\x61\
-\x02\0\0\0\0\0\x4f\x12\0\0\0\0\0\0\x71\x63\x04\0\0\0\0\0\x67\x03\0\0\x10\0\0\0\
-\x71\x61\x05\0\0\0\0\0\x67\x01\0\0\x18\0\0\0\x4f\x31\0\0\0\0\0\0\x4f\x21\0\0\0\
-\0\0\0\x71\xa2\x53\xff\0\0\0\0\x15\x02\x42\0\0\0\0\0\xbf\x12\0\0\0\0\0\0\x57\
-\x02\0\0\x10\0\0\0\x15\x02\x3f\0\0\0\0\0\x57\x01\0\0\x80\0\0\0\xb7\x02\0\0\x10\
-\0\0\0\xb7\x03\0\0\x10\0\0\0\x15\x01\x01\0\0\0\0\0\xb7\x03\0\0\x30\0\0\0\x71\
-\xa4\x55\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\x32\0\0\0\0\0\0\xbf\xa3\0\0\0\0\
-\0\0\x07\x03\0\0\x5c\xff\xff\xff\xbf\x34\0\0\0\0\0\0\x15\x01\x02\0\0\0\0\0\xbf\
-\xa4\0\0\0\0\0\0\x07\x04\0\0\x7c\xff\xff\xff\x71\xa5\x54\xff\0\0\0\0\xbf\x31\0\
-\0\0\0\0\0\x15\x05\x01\0\0\0\0\0\xbf\x41\0\0\0\0\0\0\x61\x14\x04\0\0\0\0\0\x67\
-\x04\0\0\x20\0\0\0\x61\x15\0\0\0\0\0\0\x4f\x54\0\0\0\0\0\0\x7b\x4a\xa0\xff\0\0\
-\0\0\x61\x14\x08\0\0\0\0\0\x61\x11\x0c\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x4f\x41\
-\0\0\0\0\0\0\x7b\x1a\xa8\xff\0\0\0\0\x0f\x23\0\0\0\0\0\0\x61\x31\0\0\0\0\0\0\
-\x61\x32\x04\0\0\0\0\0\x61\x34\x08\0\0\0\0\0\x61\x33\x0c\0\0\0\0\0\x69\xa5\x5a\
-\xff\0\0\0\0\x6b\x5a\xc2\xff\0\0\0\0\x69\xa5\x58\xff\0\0\0\0\x6b\x5a\xc0\xff\0\
-\0\0\0\x67\x03\0\0\x20\0\0\0\x4f\x43\0\0\0\0\0\0\x7b\x3a\xb8\xff\0\0\0\0\x67\
-\x02\0\0\x20\0\0\0\x4f\x12\0\0\0\0\0\0\x7b\x2a\xb0\xff\0\0\0\0\x05\0\x6a\0\0\0\
-\0\0\x71\xa2\x52\xff\0\0\0\0\x15\x02\x04\0\0\0\0\0\xbf\x12\0\0\0\0\0\0\x57\x02\
-\0\0\x04\0\0\0\x15\x02\x01\0\0\0\0\0\x05\0\xf1\xfe\0\0\0\0\x57\x01\0\0\x01\0\0\
-\0\x15\x01\xcb\0\0\0\0\0\x61\xa1\x5c\xff\0\0\0\0\x63\x1a\xa0\xff\0\0\0\0\x61\
-\xa1\x60\xff\0\0\0\0\x63\x1a\xa4\xff\0\0\0\0\x05\0\x5d\0\0\0\0\0\xb7\x09\0\0\
-\x3c\0\0\0\x79\xa8\x20\xff\0\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x15\
-\0\xac\xff\0\0\0\0\x05\0\xc0\0\0\0\0\0\x71\xa2\x52\xff\0\0\0\0\x15\x02\x26\0\0\
-\0\0\0\xbf\x12\0\0\0\0\0\0\x57\x02\0\0\x20\0\0\0\x15\x02\x23\0\0\0\0\0\x57\x01\
-\0\0\0\x01\0\0\xb7\x02\0\0\x10\0\0\0\xb7\x03\0\0\x10\0\0\0\x15\x01\x01\0\0\0\0\
-\0\xb7\x03\0\0\x30\0\0\0\x71\xa4\x55\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\x32\
-\0\0\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\x5c\xff\xff\xff\xbf\x34\0\0\0\0\0\
-\0\x15\x01\x02\0\0\0\0\0\xbf\xa4\0\0\0\0\0\0\x07\x04\0\0\x7c\xff\xff\xff\x71\
-\xa5\x54\xff\0\0\0\0\xbf\x31\0\0\0\0\0\0\x15\x05\xbd\xff\0\0\0\0\x05\0\xbb\xff\
-\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\x52\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x7b\
-\x1a\xc8\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\xc8\xff\xff\xff\x79\xa1\
-\x38\xff\0\0\0\0\x79\xa2\x40\xff\0\0\0\0\xb7\x04\0\0\x08\0\0\0\xb7\x05\0\0\x01\
-\0\0\0\x85\0\0\0\x44\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x55\0\x9b\0\
-\0\0\0\0\x05\0\xa8\xfe\0\0\0\0\x15\x09\xf3\xfe\x87\0\0\0\x05\0\x83\xff\0\0\0\0\
-\xbf\x12\0\0\0\0\0\0\x57\x02\0\0\x08\0\0\0\x15\x02\x95\0\0\0\0\0\x57\x01\0\0\
-\x40\0\0\0\xb7\x02\0\0\x0c\0\0\0\xb7\x03\0\0\x0c\0\0\0\x15\x01\x01\0\0\0\0\0\
-\xb7\x03\0\0\x2c\0\0\0\x71\xa4\x54\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\x32\0\
-\0\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\x50\xff\xff\xff\x0f\x23\0\0\0\0\0\0\
-\x61\x32\x04\0\0\0\0\0\x67\x02\0\0\x20\0\0\0\x61\x34\0\0\0\0\0\0\x4f\x42\0\0\0\
-\0\0\0\x7b\x2a\xa0\xff\0\0\0\0\x61\x32\x08\0\0\0\0\0\x61\x33\x0c\0\0\0\0\0\x67\
-\x03\0\0\x20\0\0\0\x4f\x23\0\0\0\0\0\0\x7b\x3a\xa8\xff\0\0\0\0\xbf\xa2\0\0\0\0\
-\0\0\x07\x02\0\0\xb0\xff\xff\xff\x71\xa3\x55\xff\0\0\0\0\x15\x03\x0b\0\0\0\0\0\
-\x15\x01\x0a\0\0\0\0\0\x61\xa1\x98\xff\0\0\0\0\x63\x12\x0c\0\0\0\0\0\x61\xa1\
-\x94\xff\0\0\0\0\x63\x12\x08\0\0\0\0\0\x61\xa1\x90\xff\0\0\0\0\x63\x12\x04\0\0\
-\0\0\0\x61\xa1\x8c\xff\0\0\0\0\x05\0\x09\0\0\0\0\0\xb7\x09\0\0\x2b\0\0\0\x05\0\
-\xad\xff\0\0\0\0\x61\xa1\x78\xff\0\0\0\0\x63\x12\x0c\0\0\0\0\0\x61\xa1\x74\xff\
-\0\0\0\0\x63\x12\x08\0\0\0\0\0\x61\xa1\x70\xff\0\0\0\0\x63\x12\x04\0\0\0\0\0\
-\x61\xa1\x6c\xff\0\0\0\0\x63\x12\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x07\x08\0\0\
-\x04\0\0\0\x61\x03\0\0\0\0\0\0\xb7\x05\0\0\0\0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\
-\0\0\xa0\xff\xff\xff\x0f\x12\0\0\0\0\0\0\x71\x24\0\0\0\0\0\0\xbf\x42\0\0\0\0\0\
-\0\x67\x02\0\0\x38\0\0\0\xc7\x02\0\0\x3f\0\0\0\x5f\x32\0\0\0\0\0\0\xaf\x52\0\0\
-\0\0\0\0\xbf\x85\0\0\0\0\0\0\x0f\x15\0\0\0\0\0\0\x71\x55\0\0\0\0\0\0\x67\x03\0\
-\0\x01\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x07\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\
-\x40\0\0\0\0\0\0\x67\0\0\0\x39\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\
-\xaf\x02\0\0\0\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x06\0\0\0\x57\0\0\0\x01\0\0\
-\0\x67\x03\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3a\
-\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\0\0\x67\x03\0\0\
-\x01\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x05\0\0\0\x57\0\0\0\x01\0\0\0\x4f\x03\
-\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3b\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\
-\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\0\0\x67\x03\0\0\x01\0\0\0\xbf\x50\0\0\0\0\0\0\
-\x77\0\0\0\x04\0\0\0\x57\0\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\
-\0\x67\0\0\0\x3c\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\
-\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x03\0\0\0\x57\0\0\0\x01\0\0\0\x67\x03\0\0\
-\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3d\0\0\0\xc7\0\0\
-\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\
-\0\0\x02\0\0\0\x57\0\0\0\x01\0\0\0\x67\x03\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\
-\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3e\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\
-\0\xaf\x02\0\0\0\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x01\0\0\0\x57\0\0\0\x01\0\
-\0\0\x67\x03\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\x57\x04\0\0\x01\0\0\0\x87\x04\0\
-\0\0\0\0\0\x5f\x34\0\0\0\0\0\0\xaf\x42\0\0\0\0\0\0\x57\x05\0\0\x01\0\0\0\x67\
-\x03\0\0\x01\0\0\0\x4f\x53\0\0\0\0\0\0\x07\x01\0\0\x01\0\0\0\xbf\x25\0\0\0\0\0\
-\0\x15\x01\x01\0\x24\0\0\0\x05\0\xa9\xff\0\0\0\0\x71\x61\x06\0\0\0\0\0\x71\x63\
-\x07\0\0\0\0\0\x67\x03\0\0\x08\0\0\0\x4f\x13\0\0\0\0\0\0\x67\x02\0\0\x20\0\0\0\
-\x77\x02\0\0\x20\0\0\0\x9f\x32\0\0\0\0\0\0\x63\x2a\x50\xff\0\0\0\0\xbf\xa2\0\0\
-\0\0\0\0\x07\x02\0\0\x50\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x85\0\
-\0\0\x01\0\0\0\x55\0\x05\0\0\0\0\0\x71\x61\x08\0\0\0\0\0\x71\x60\x09\0\0\0\0\0\
-\x67\0\0\0\x08\0\0\0\x4f\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x69\0\0\0\0\0\0\0\
-\x05\0\xfd\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\x07\x01\0\0\x7c\xff\xff\xff\x7b\x1a\x10\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x7b\
+\x1a\x28\xff\0\0\0\0\x7b\x8a\x20\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\
+\xf8\xff\xff\xff\x79\xa1\x40\xff\0\0\0\0\x79\xa2\x38\xff\0\0\0\0\xb7\x04\0\0\
+\x02\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\
+\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\xc8\0\0\0\0\0\xbf\x91\0\0\0\0\
+\0\0\x15\x01\x24\0\x3c\0\0\0\x15\x01\x5c\0\x2c\0\0\0\x55\x01\x5d\0\x2b\0\0\0\
+\xb7\x01\0\0\0\0\0\0\x63\x1a\xf0\xff\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\
+\xf0\xff\xff\xff\x79\xa9\x40\xff\0\0\0\0\xbf\x91\0\0\0\0\0\0\x79\xa2\x38\xff\0\
+\0\0\0\xb7\x04\0\0\x04\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\xbf\x01\
+\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\x07\x01\0\0\0\
+\0\x71\xa1\xf2\xff\0\0\0\0\x55\x01\x4d\0\x02\0\0\0\x71\xa1\xf1\xff\0\0\0\0\x55\
+\x01\x4b\0\x02\0\0\0\x71\xa1\xf3\xff\0\0\0\0\x55\x01\x49\0\x01\0\0\0\x79\xa2\
+\x38\xff\0\0\0\0\x07\x02\0\0\x08\0\0\0\xbf\x91\0\0\0\0\0\0\x79\xa3\x18\xff\0\0\
+\0\0\xb7\x04\0\0\x10\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\
+\0\0\0\0\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\xf6\0\0\0\0\0\
+\xb7\x01\0\0\x01\0\0\0\x73\x1a\x55\xff\0\0\0\0\x05\0\x3b\0\0\0\0\0\xb7\x08\0\0\
+\x02\0\0\0\xb7\x07\0\0\0\0\0\0\x6b\x7a\xf0\xff\0\0\0\0\x05\0\x12\0\0\0\0\0\x0f\
+\x81\0\0\0\0\0\0\xbf\x12\0\0\0\0\0\0\x07\x02\0\0\x01\0\0\0\x71\xa3\xf9\xff\0\0\
+\0\0\x67\x03\0\0\x03\0\0\0\x3d\x32\x09\0\0\0\0\0\xbf\x72\0\0\0\0\0\0\x07\x02\0\
+\0\x01\0\0\0\x67\x07\0\0\x20\0\0\0\xbf\x73\0\0\0\0\0\0\x77\x03\0\0\x20\0\0\0\
+\xbf\x27\0\0\0\0\0\0\xbf\x18\0\0\0\0\0\0\xb7\x01\0\0\x1d\0\0\0\x2d\x31\x03\0\0\
+\0\0\0\x79\xa8\x20\xff\0\0\0\0\x79\xa7\x30\xff\0\0\0\0\x05\0\x25\0\0\0\0\0\xbf\
+\x89\0\0\0\0\0\0\x79\xa1\x38\xff\0\0\0\0\x0f\x19\0\0\0\0\0\0\xbf\xa3\0\0\0\0\0\
+\0\x07\x03\0\0\xf0\xff\xff\xff\x79\xa1\x40\xff\0\0\0\0\xbf\x92\0\0\0\0\0\0\xb7\
+\x04\0\0\x02\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\
+\0\x67\x01\0\0\x20\0\0\0\x77\x01\0\0\x20\0\0\0\x55\x01\x7b\0\0\0\0\0\x71\xa2\
+\xf0\xff\0\0\0\0\x55\x02\x0e\0\xc9\0\0\0\x07\x09\0\0\x02\0\0\0\x79\xa1\x40\xff\
+\0\0\0\0\xbf\x92\0\0\0\0\0\0\x79\xa3\x10\xff\0\0\0\0\xb7\x04\0\0\x10\0\0\0\xb7\
+\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\0\xbf\x01\0\0\0\0\0\0\x67\x01\0\0\x20\0\0\
+\0\x77\x01\0\0\x20\0\0\0\x55\x01\x6e\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x1a\
+\x54\xff\0\0\0\0\x05\0\xdf\xff\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\x02\xce\xff\0\
+\0\0\0\x71\xa1\xf1\xff\0\0\0\0\x07\x01\0\0\x02\0\0\0\x05\0\xcb\xff\0\0\0\0\xb7\
+\x01\0\0\x01\0\0\0\x73\x1a\x56\xff\0\0\0\0\x71\xa1\xf9\xff\0\0\0\0\x67\x01\0\0\
+\x03\0\0\0\x79\xa2\x38\xff\0\0\0\0\x0f\x12\0\0\0\0\0\0\x07\x02\0\0\x08\0\0\0\
+\x7b\x2a\x38\xff\0\0\0\0\x71\xa9\xf8\xff\0\0\0\0\x25\x09\x0f\0\x3c\0\0\0\xb7\
+\x01\0\0\x01\0\0\0\x6f\x91\0\0\0\0\0\0\x18\x02\0\0\x01\0\0\0\0\0\0\0\0\x18\0\
+\x1c\x5f\x21\0\0\0\0\0\0\x55\x01\x01\0\0\0\0\0\x05\0\x08\0\0\0\0\0\x79\xa1\x28\
+\xff\0\0\0\0\x07\x01\0\0\x01\0\0\0\x7b\x1a\x28\xff\0\0\0\0\x67\x01\0\0\x20\0\0\
+\0\x77\x01\0\0\x20\0\0\0\x55\x01\x7f\xff\x0b\0\0\0\x71\xa7\x56\xff\0\0\0\0\x05\
+\0\x0b\xff\0\0\0\0\x15\x09\xf7\xff\x87\0\0\0\x05\0\xfc\xff\0\0\0\0\x71\xa1\x51\
+\xff\0\0\0\0\x79\xa0\x30\xff\0\0\0\0\x15\x01\x0f\x01\0\0\0\0\x71\x62\x03\0\0\0\
+\0\0\x67\x02\0\0\x08\0\0\0\x71\x61\x02\0\0\0\0\0\x4f\x12\0\0\0\0\0\0\x71\x63\
+\x04\0\0\0\0\0\x67\x03\0\0\x10\0\0\0\x71\x61\x05\0\0\0\0\0\x67\x01\0\0\x18\0\0\
+\0\x4f\x31\0\0\0\0\0\0\x4f\x21\0\0\0\0\0\0\x71\xa2\x53\xff\0\0\0\0\x15\x02\x43\
+\0\0\0\0\0\xbf\x12\0\0\0\0\0\0\x57\x02\0\0\x10\0\0\0\x15\x02\x40\0\0\0\0\0\x57\
+\x01\0\0\x80\0\0\0\xb7\x02\0\0\x10\0\0\0\xb7\x03\0\0\x10\0\0\0\x15\x01\x01\0\0\
+\0\0\0\xb7\x03\0\0\x30\0\0\0\x71\xa4\x55\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\
+\x32\0\0\0\0\0\0\xbf\xa3\0\0\0\0\0\0\x07\x03\0\0\x5c\xff\xff\xff\xbf\x34\0\0\0\
+\0\0\0\x15\x01\x02\0\0\0\0\0\xbf\xa4\0\0\0\0\0\0\x07\x04\0\0\x7c\xff\xff\xff\
+\x71\xa5\x54\xff\0\0\0\0\xbf\x31\0\0\0\0\0\0\x15\x05\x01\0\0\0\0\0\xbf\x41\0\0\
+\0\0\0\0\x61\x14\x04\0\0\0\0\0\x67\x04\0\0\x20\0\0\0\x61\x15\0\0\0\0\0\0\x4f\
+\x54\0\0\0\0\0\0\x7b\x4a\xa0\xff\0\0\0\0\x61\x14\x08\0\0\0\0\0\x61\x11\x0c\0\0\
+\0\0\0\x67\x01\0\0\x20\0\0\0\x4f\x41\0\0\0\0\0\0\x7b\x1a\xa8\xff\0\0\0\0\x0f\
+\x23\0\0\0\0\0\0\x61\x31\0\0\0\0\0\0\x61\x32\x04\0\0\0\0\0\x61\x34\x08\0\0\0\0\
+\0\x61\x33\x0c\0\0\0\0\0\x69\xa5\x5a\xff\0\0\0\0\x6b\x5a\xc2\xff\0\0\0\0\x69\
+\xa5\x58\xff\0\0\0\0\x6b\x5a\xc0\xff\0\0\0\0\x67\x03\0\0\x20\0\0\0\x4f\x43\0\0\
+\0\0\0\0\x7b\x3a\xb8\xff\0\0\0\0\x67\x02\0\0\x20\0\0\0\x4f\x12\0\0\0\0\0\0\x7b\
+\x2a\xb0\xff\0\0\0\0\x05\0\x6b\0\0\0\0\0\x71\xa2\x52\xff\0\0\0\0\x15\x02\x04\0\
+\0\0\0\0\xbf\x12\0\0\0\0\0\0\x57\x02\0\0\x04\0\0\0\x15\x02\x01\0\0\0\0\0\x05\0\
+\xf3\xfe\0\0\0\0\x57\x01\0\0\x01\0\0\0\x15\x01\xcc\0\0\0\0\0\x61\xa1\x5c\xff\0\
+\0\0\0\x63\x1a\xa0\xff\0\0\0\0\x61\xa1\x60\xff\0\0\0\0\x63\x1a\xa4\xff\0\0\0\0\
+\x05\0\x5e\0\0\0\0\0\xb7\x09\0\0\x3c\0\0\0\x79\xa8\x20\xff\0\0\0\0\x79\xa7\x30\
+\xff\0\0\0\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x15\0\xab\xff\0\0\0\0\x05\
+\0\xc0\0\0\0\0\0\x71\xa2\x52\xff\0\0\0\0\x15\x02\x26\0\0\0\0\0\xbf\x12\0\0\0\0\
+\0\0\x57\x02\0\0\x20\0\0\0\x15\x02\x23\0\0\0\0\0\x57\x01\0\0\0\x01\0\0\xb7\x02\
+\0\0\x10\0\0\0\xb7\x03\0\0\x10\0\0\0\x15\x01\x01\0\0\0\0\0\xb7\x03\0\0\x30\0\0\
+\0\x71\xa4\x55\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\x32\0\0\0\0\0\0\xbf\xa3\0\
+\0\0\0\0\0\x07\x03\0\0\x5c\xff\xff\xff\xbf\x34\0\0\0\0\0\0\x15\x01\x02\0\0\0\0\
+\0\xbf\xa4\0\0\0\0\0\0\x07\x04\0\0\x7c\xff\xff\xff\x71\xa5\x54\xff\0\0\0\0\xbf\
+\x31\0\0\0\0\0\0\x15\x05\xbc\xff\0\0\0\0\x05\0\xba\xff\0\0\0\0\xb7\x01\0\0\x01\
+\0\0\0\x73\x1a\x52\xff\0\0\0\0\xb7\x01\0\0\0\0\0\0\x7b\x1a\xc8\xff\0\0\0\0\xbf\
+\xa3\0\0\0\0\0\0\x07\x03\0\0\xc8\xff\xff\xff\x79\xa1\x40\xff\0\0\0\0\x79\xa2\
+\x38\xff\0\0\0\0\xb7\x04\0\0\x08\0\0\0\xb7\x05\0\0\x01\0\0\0\x85\0\0\0\x44\0\0\
+\0\x67\0\0\0\x20\0\0\0\x77\0\0\0\x20\0\0\0\x55\0\x9b\0\0\0\0\0\x05\0\xa9\xfe\0\
+\0\0\0\x15\x09\xf5\xfe\x87\0\0\0\x05\0\x82\xff\0\0\0\0\xbf\x12\0\0\0\0\0\0\x57\
+\x02\0\0\x08\0\0\0\x15\x02\x95\0\0\0\0\0\x57\x01\0\0\x40\0\0\0\xb7\x02\0\0\x0c\
+\0\0\0\xb7\x03\0\0\x0c\0\0\0\x15\x01\x01\0\0\0\0\0\xb7\x03\0\0\x2c\0\0\0\x71\
+\xa4\x54\xff\0\0\0\0\x15\x04\x01\0\0\0\0\0\xbf\x32\0\0\0\0\0\0\xbf\xa3\0\0\0\0\
+\0\0\x07\x03\0\0\x50\xff\xff\xff\x0f\x23\0\0\0\0\0\0\x61\x32\x04\0\0\0\0\0\x67\
+\x02\0\0\x20\0\0\0\x61\x34\0\0\0\0\0\0\x4f\x42\0\0\0\0\0\0\x7b\x2a\xa0\xff\0\0\
+\0\0\x61\x32\x08\0\0\0\0\0\x61\x33\x0c\0\0\0\0\0\x67\x03\0\0\x20\0\0\0\x4f\x23\
+\0\0\0\0\0\0\x7b\x3a\xa8\xff\0\0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xb0\xff\
+\xff\xff\x71\xa3\x55\xff\0\0\0\0\x15\x03\x0b\0\0\0\0\0\x15\x01\x0a\0\0\0\0\0\
+\x61\xa1\x98\xff\0\0\0\0\x63\x12\x0c\0\0\0\0\0\x61\xa1\x94\xff\0\0\0\0\x63\x12\
+\x08\0\0\0\0\0\x61\xa1\x90\xff\0\0\0\0\x63\x12\x04\0\0\0\0\0\x61\xa1\x8c\xff\0\
+\0\0\0\x05\0\x09\0\0\0\0\0\xb7\x09\0\0\x2b\0\0\0\x05\0\xad\xff\0\0\0\0\x61\xa1\
+\x78\xff\0\0\0\0\x63\x12\x0c\0\0\0\0\0\x61\xa1\x74\xff\0\0\0\0\x63\x12\x08\0\0\
+\0\0\0\x61\xa1\x70\xff\0\0\0\0\x63\x12\x04\0\0\0\0\0\x61\xa1\x6c\xff\0\0\0\0\
+\x63\x12\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x07\x08\0\0\x04\0\0\0\x61\x03\0\0\0\0\
+\0\0\xb7\x05\0\0\0\0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xa0\xff\xff\xff\x0f\
+\x12\0\0\0\0\0\0\x71\x24\0\0\0\0\0\0\xbf\x42\0\0\0\0\0\0\x67\x02\0\0\x38\0\0\0\
+\xc7\x02\0\0\x3f\0\0\0\x5f\x32\0\0\0\0\0\0\xaf\x52\0\0\0\0\0\0\xbf\x85\0\0\0\0\
+\0\0\x0f\x15\0\0\0\0\0\0\x71\x55\0\0\0\0\0\0\x67\x03\0\0\x01\0\0\0\xbf\x50\0\0\
+\0\0\0\0\x77\0\0\0\x07\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\
+\x39\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\0\0\xbf\x50\
+\0\0\0\0\0\0\x77\0\0\0\x06\0\0\0\x57\0\0\0\x01\0\0\0\x67\x03\0\0\x01\0\0\0\x4f\
+\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3a\0\0\0\xc7\0\0\0\x3f\0\0\0\
+\x5f\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\0\0\x67\x03\0\0\x01\0\0\0\xbf\x50\0\0\0\0\
+\0\0\x77\0\0\0\x05\0\0\0\x57\0\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\
+\0\0\0\x67\0\0\0\x3b\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x02\0\0\
+\0\0\0\0\x67\x03\0\0\x01\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x04\0\0\0\x57\0\0\
+\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3c\0\0\0\xc7\0\
+\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\0\0\xbf\x50\0\0\0\0\0\0\x77\
+\0\0\0\x03\0\0\0\x57\0\0\0\x01\0\0\0\x67\x03\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\
+\xbf\x40\0\0\0\0\0\0\x67\0\0\0\x3d\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\
+\0\xaf\x02\0\0\0\0\0\0\xbf\x50\0\0\0\0\0\0\x77\0\0\0\x02\0\0\0\x57\0\0\0\x01\0\
+\0\0\x67\x03\0\0\x01\0\0\0\x4f\x03\0\0\0\0\0\0\xbf\x40\0\0\0\0\0\0\x67\0\0\0\
+\x3e\0\0\0\xc7\0\0\0\x3f\0\0\0\x5f\x30\0\0\0\0\0\0\xaf\x02\0\0\0\0\0\0\xbf\x50\
+\0\0\0\0\0\0\x77\0\0\0\x01\0\0\0\x57\0\0\0\x01\0\0\0\x67\x03\0\0\x01\0\0\0\x4f\
+\x03\0\0\0\0\0\0\x57\x04\0\0\x01\0\0\0\x87\x04\0\0\0\0\0\0\x5f\x34\0\0\0\0\0\0\
+\xaf\x42\0\0\0\0\0\0\x57\x05\0\0\x01\0\0\0\x67\x03\0\0\x01\0\0\0\x4f\x53\0\0\0\
+\0\0\0\x07\x01\0\0\x01\0\0\0\xbf\x25\0\0\0\0\0\0\x15\x01\x01\0\x24\0\0\0\x05\0\
+\xa9\xff\0\0\0\0\x71\x61\x06\0\0\0\0\0\x71\x63\x07\0\0\0\0\0\x67\x03\0\0\x08\0\
+\0\0\x4f\x13\0\0\0\0\0\0\x67\x02\0\0\x20\0\0\0\x77\x02\0\0\x20\0\0\0\x9f\x32\0\
+\0\0\0\0\0\x63\x2a\x50\xff\0\0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\x50\xff\xff\
+\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\x55\0\x07\0\0\0\0\
+\0\x71\x61\x08\0\0\0\0\0\x71\x69\x09\0\0\0\0\0\x67\x09\0\0\x08\0\0\0\x4f\x19\0\
+\0\0\0\0\0\x57\x09\0\0\xff\xff\0\0\xbf\x90\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x69\
+\x09\0\0\0\0\0\0\x05\0\xfb\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x47\x50\x4c\x20\x76\
-\x32\0\0\x9f\xeb\x01\0\x18\0\0\0\0\0\0\0\x50\x05\0\0\x50\x05\0\0\x8e\x11\0\0\0\
-\0\0\0\0\0\0\x02\x03\0\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\0\
-\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x02\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\
-\x20\0\0\0\0\0\0\0\0\0\0\x02\x06\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\
-\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\x02\x08\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\
-\0\x04\0\0\0\x0a\0\0\0\0\0\0\0\0\0\0\x02\x0a\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\
-\x02\0\0\0\x04\0\0\0\x01\0\0\0\0\0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\0\0\x01\0\0\
-\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0\x27\0\0\0\x07\0\0\0\x80\0\0\0\x32\0\0\
-\0\x09\0\0\0\xc0\0\0\0\x3e\0\0\0\0\0\0\x0e\x0b\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\
-\x02\x0e\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x28\0\0\0\0\0\0\0\
-\x04\0\0\x04\x20\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\
-\0\x27\0\0\0\x0d\0\0\0\x80\0\0\0\x32\0\0\0\x09\0\0\0\xc0\0\0\0\x59\0\0\0\0\0\0\
-\x0e\x0f\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x12\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\
-\x02\0\0\0\x04\0\0\0\x80\0\0\0\0\0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\0\0\x01\0\0\
-\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0\x27\0\0\0\x01\0\0\0\x80\0\0\0\x32\0\0\
-\0\x11\0\0\0\xc0\0\0\0\x72\0\0\0\0\0\0\x0e\x13\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\
-\x02\x16\0\0\0\x90\0\0\0\x25\0\0\x04\xc8\0\0\0\x9a\0\0\0\x17\0\0\0\0\0\0\0\x9e\
-\0\0\0\x17\0\0\0\x20\0\0\0\xa7\0\0\0\x17\0\0\0\x40\0\0\0\xac\0\0\0\x17\0\0\0\
-\x60\0\0\0\xba\0\0\0\x17\0\0\0\x80\0\0\0\xc3\0\0\0\x17\0\0\0\xa0\0\0\0\xd0\0\0\
-\0\x17\0\0\0\xc0\0\0\0\xd9\0\0\0\x17\0\0\0\xe0\0\0\0\xe4\0\0\0\x17\0\0\0\0\x01\
-\0\0\xed\0\0\0\x17\0\0\0\x20\x01\0\0\xfd\0\0\0\x17\0\0\0\x40\x01\0\0\x05\x01\0\
-\0\x17\0\0\0\x60\x01\0\0\x0e\x01\0\0\x19\0\0\0\x80\x01\0\0\x11\x01\0\0\x17\0\0\
-\0\x20\x02\0\0\x16\x01\0\0\x17\0\0\0\x40\x02\0\0\x21\x01\0\0\x17\0\0\0\x60\x02\
-\0\0\x26\x01\0\0\x17\0\0\0\x80\x02\0\0\x2f\x01\0\0\x17\0\0\0\xa0\x02\0\0\x37\
-\x01\0\0\x17\0\0\0\xc0\x02\0\0\x3e\x01\0\0\x17\0\0\0\xe0\x02\0\0\x49\x01\0\0\
-\x17\0\0\0\0\x03\0\0\x53\x01\0\0\x1a\0\0\0\x20\x03\0\0\x5e\x01\0\0\x1a\0\0\0\
-\xa0\x03\0\0\x68\x01\0\0\x17\0\0\0\x20\x04\0\0\x74\x01\0\0\x17\0\0\0\x40\x04\0\
-\0\x7f\x01\0\0\x17\0\0\0\x60\x04\0\0\0\0\0\0\x1b\0\0\0\x80\x04\0\0\x89\x01\0\0\
-\x1d\0\0\0\xc0\x04\0\0\x90\x01\0\0\x17\0\0\0\0\x05\0\0\x99\x01\0\0\x17\0\0\0\
-\x20\x05\0\0\0\0\0\0\x1f\0\0\0\x40\x05\0\0\xa2\x01\0\0\x17\0\0\0\x80\x05\0\0\
-\xab\x01\0\0\x21\0\0\0\xa0\x05\0\0\xb7\x01\0\0\x1d\0\0\0\xc0\x05\0\0\xc0\x01\0\
-\0\x17\0\0\0\0\x06\0\0\xd0\x01\0\0\x23\0\0\0\x20\x06\0\0\xe1\x01\0\0\x23\0\0\0\
-\x30\x06\0\0\xf0\x01\0\0\0\0\0\x08\x18\0\0\0\xf6\x01\0\0\0\0\0\x01\x04\0\0\0\
-\x20\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x17\0\0\0\x04\0\0\0\x05\0\0\0\0\0\0\0\0\0\
-\0\x03\0\0\0\0\x17\0\0\0\x04\0\0\0\x04\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\x03\
-\x02\0\0\x1c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x2c\0\0\0\x0d\x02\0\0\0\0\0\x08\
-\x1e\0\0\0\x13\x02\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\
-\0\0\x26\x02\0\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x2d\0\0\0\x29\x02\0\0\0\0\
-\0\x08\x22\0\0\0\x2e\x02\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\0\x3c\x02\0\0\0\0\0\
-\x08\x24\0\0\0\x42\x02\0\0\0\0\0\x01\x02\0\0\0\x10\0\0\0\0\0\0\0\x01\0\0\x0d\
-\x02\0\0\0\x51\x02\0\0\x15\0\0\0\x55\x02\0\0\x01\0\0\x0c\x25\0\0\0\x5b\x11\0\0\
-\0\0\0\x01\x01\0\0\0\x08\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x27\0\0\0\x04\0\0\0\
-\x07\0\0\0\x60\x11\0\0\0\0\0\x0e\x28\0\0\0\x01\0\0\0\x69\x11\0\0\x03\0\0\x0f\0\
-\0\0\0\x0c\0\0\0\0\0\0\0\x20\0\0\0\x10\0\0\0\0\0\0\0\x20\0\0\0\x14\0\0\0\0\0\0\
-\0\x20\0\0\0\x6f\x11\0\0\x01\0\0\x0f\0\0\0\0\x29\0\0\0\0\0\0\0\x07\0\0\0\x77\
-\x11\0\0\0\0\0\x07\0\0\0\0\x85\x11\0\0\0\0\0\x07\0\0\0\0\0\x69\x6e\x74\0\x5f\
-\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x74\
-\x79\x70\x65\0\x6b\x65\x79\x5f\x73\x69\x7a\x65\0\x76\x61\x6c\x75\x65\x5f\x73\
-\x69\x7a\x65\0\x6d\x61\x78\x5f\x65\x6e\x74\x72\x69\x65\x73\0\x74\x61\x70\x5f\
-\x72\x73\x73\x5f\x6d\x61\x70\x5f\x63\x6f\x6e\x66\x69\x67\x75\x72\x61\x74\x69\
-\x6f\x6e\x73\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x74\x6f\x65\x70\
-\x6c\x69\x74\x7a\x5f\x6b\x65\x79\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\
-\x5f\x69\x6e\x64\x69\x72\x65\x63\x74\x69\x6f\x6e\x5f\x74\x61\x62\x6c\x65\0\x5f\
-\x5f\x73\x6b\x5f\x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\x79\x70\
-\x65\0\x6d\x61\x72\x6b\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\
-\x70\x72\x6f\x74\x6f\x63\x6f\x6c\0\x76\x6c\x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\
-\x74\0\x76\x6c\x61\x6e\x5f\x74\x63\x69\0\x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\
-\x6f\0\x70\x72\x69\x6f\x72\x69\x74\x79\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\
-\x66\x69\x6e\x64\x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\
-\x64\x65\x78\0\x63\x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\
-\x64\0\x64\x61\x74\x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\
-\x69\x64\0\x66\x61\x6d\x69\x6c\x79\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\
-\x6c\x6f\x63\x61\x6c\x5f\x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\
-\0\x6c\x6f\x63\x61\x6c\x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\
-\x72\x74\0\x6c\x6f\x63\x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\
-\x65\x74\x61\0\x74\x73\x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\
-\x73\x6f\x5f\x73\x65\x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x74\x73\x74\
-\x61\x6d\x70\x5f\x74\x79\x70\x65\0\x68\x77\x74\x73\x74\x61\x6d\x70\0\x76\x6e\
-\x65\x74\x5f\x68\x61\x73\x68\x5f\x76\x61\x6c\x75\x65\0\x76\x6e\x65\x74\x5f\x68\
-\x61\x73\x68\x5f\x72\x65\x70\x6f\x72\x74\0\x76\x6e\x65\x74\x5f\x72\x73\x73\x5f\
-\x71\x75\x65\x75\x65\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\x6e\x65\x64\
-\x20\x69\x6e\x74\0\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x5f\x5f\x75\x36\x34\0\
-\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\0\x73\
-\x6b\0\x5f\x5f\x75\x38\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\
-\x5f\x5f\x75\x31\x36\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x73\x68\x6f\x72\x74\
-\0\x73\x6b\x62\0\x74\x75\x6e\x5f\x72\x73\x73\x5f\x73\x74\x65\x65\x72\x69\x6e\
-\x67\x5f\x70\x72\x6f\x67\0\x73\x6f\x63\x6b\x65\x74\0\x2f\x68\x6f\x6d\x65\x2f\
-\x61\x6c\x61\x72\x6d\x2f\x71\x2f\x76\x61\x72\x2f\x71\x65\x6d\x75\x2f\x74\x6f\
-\x6f\x6c\x73\x2f\x65\x62\x70\x66\x2f\x72\x73\x73\x2e\x62\x70\x66\x2e\x63\0\x69\
-\x6e\x74\x20\x74\x75\x6e\x5f\x72\x73\x73\x5f\x73\x74\x65\x65\x72\x69\x6e\x67\
-\x5f\x70\x72\x6f\x67\x28\x73\x74\x72\x75\x63\x74\x20\x5f\x5f\x73\x6b\x5f\x62\
-\x75\x66\x66\x20\x2a\x73\x6b\x62\x29\0\x20\x20\x20\x20\x5f\x5f\x75\x33\x32\x20\
-\x6b\x65\x79\x20\x3d\x20\x30\x3b\0\x20\x20\x20\x20\x63\x6f\x6e\x66\x69\x67\x20\
-\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\
-\x65\x6d\x28\x26\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x63\x6f\x6e\
-\x66\x69\x67\x75\x72\x61\x74\x69\x6f\x6e\x73\x2c\x20\x26\x6b\x65\x79\x29\x3b\0\
-\x20\x20\x20\x20\x74\x6f\x65\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\
-\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x74\x61\x70\x5f\x72\x73\x73\
-\x5f\x6d\x61\x70\x5f\x74\x6f\x65\x70\x6c\x69\x74\x7a\x5f\x6b\x65\x79\x2c\x20\
-\x26\x6b\x65\x79\x29\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\x63\x6f\x6e\x66\x69\
-\x67\x20\x26\x26\x20\x74\x6f\x65\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\
-\x69\x66\x20\x28\x21\x63\x6f\x6e\x66\x69\x67\x2d\x3e\x72\x65\x64\x69\x72\x65\
-\x63\x74\x29\x20\x7b\0\x20\x20\x20\x20\x5f\x5f\x75\x38\x20\x72\x73\x73\x5f\x69\
-\x6e\x70\x75\x74\x5b\x48\x41\x53\x48\x5f\x43\x41\x4c\x43\x55\x4c\x41\x54\x49\
-\x4f\x4e\x5f\x42\x55\x46\x46\x45\x52\x5f\x53\x49\x5a\x45\x5d\x20\x3d\x20\x7b\
-\x7d\x3b\0\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x70\x61\x63\x6b\x65\x74\
-\x5f\x68\x61\x73\x68\x5f\x69\x6e\x66\x6f\x5f\x74\x20\x70\x61\x63\x6b\x65\x74\
-\x5f\x69\x6e\x66\x6f\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\
-\x21\x69\x6e\x66\x6f\x20\x7c\x7c\x20\x21\x73\x6b\x62\x29\x20\x7b\0\x20\x20\x20\
-\x20\x5f\x5f\x62\x65\x31\x36\x20\x72\x65\x74\x20\x3d\x20\x30\x3b\0\x20\x20\x20\
-\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\
-\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\
-\x2c\x20\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x72\x65\x74\x2c\x20\x73\x69\x7a\
-\x65\x6f\x66\x28\x72\x65\x74\x29\x2c\0\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\
-\x72\x29\x20\x7b\0\x20\x20\x20\x20\x73\x77\x69\x74\x63\x68\x20\x28\x62\x70\x66\
-\x5f\x6e\x74\x6f\x68\x73\x28\x72\x65\x74\x29\x29\x20\x7b\0\x20\x20\x20\x20\x20\
-\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\
-\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\
-\x6b\x62\x2c\x20\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x72\x65\x74\x2c\x20\x73\
-\x69\x7a\x65\x6f\x66\x28\x72\x65\x74\x29\x2c\0\x20\x20\x20\x20\x72\x65\x74\x75\
-\x72\x6e\x20\x72\x65\x74\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\x6c\x33\x5f\x70\
-\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x3d\x20\x30\x29\x20\x7b\0\x20\x20\x20\x20\
-\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x69\x70\x76\x34\x20\x3d\
-\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x69\
-\x70\x68\x64\x72\x20\x69\x70\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\
-\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\
-\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\
-\x62\x2c\x20\x30\x2c\x20\x26\x69\x70\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\x69\
-\x70\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x29\
-\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\
-\x66\x72\x61\x67\x6d\x65\x6e\x74\x65\x64\x20\x3d\x20\x21\x21\x69\x70\x2e\x66\
-\x72\x61\x67\x5f\x6f\x66\x66\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\
-\x6f\x2d\x3e\x69\x6e\x5f\x73\x72\x63\x20\x3d\x20\x69\x70\x2e\x73\x61\x64\x64\
-\x72\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x6e\x5f\
-\x64\x73\x74\x20\x3d\x20\x69\x70\x2e\x64\x61\x64\x64\x72\x3b\0\x20\x20\x20\x20\
-\x20\x20\x20\x20\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x20\x69\
-\x70\x2e\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\
-\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x3d\x20\x69\x70\x2e\x69\x68\x6c\x20\
-\x2a\x20\x34\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\x6c\x34\x5f\x70\x72\x6f\x74\
-\x6f\x63\x6f\x6c\x20\x21\x3d\x20\x30\x20\x26\x26\x20\x21\x69\x6e\x66\x6f\x2d\
-\x3e\x69\x73\x5f\x66\x72\x61\x67\x6d\x65\x6e\x74\x65\x64\x29\x20\x7b\0\x20\x20\
-\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\
-\x6f\x6c\x20\x3d\x3d\x20\x49\x50\x50\x52\x4f\x54\x4f\x5f\x54\x43\x50\x29\x20\
-\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\
-\x69\x73\x5f\x74\x63\x70\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x74\x63\x70\x68\x64\x72\x20\x74\
-\x63\x70\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\
-\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\
-\x2c\x20\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x74\x63\x70\x2c\x20\
-\x73\x69\x7a\x65\x6f\x66\x28\x74\x63\x70\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x29\x20\x7b\0\x20\x20\x20\x20\
-\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\
-\x69\x70\x76\x34\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\
-\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\x74\x63\x70\x20\
-\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\
-\x69\x70\x76\x36\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\
-\x72\x75\x63\x74\x20\x69\x70\x76\x36\x68\x64\x72\x20\x69\x70\x36\x20\x3d\x20\
-\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\
-\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\
-\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x30\x2c\x20\x26\x69\x70\x36\
-\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\x69\x70\x36\x29\x2c\0\x20\x20\x20\x20\x20\
-\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x6e\x36\x5f\x73\x72\x63\x20\x3d\x20\
-\x69\x70\x36\x2e\x73\x61\x64\x64\x72\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\
-\x6e\x66\x6f\x2d\x3e\x69\x6e\x36\x5f\x64\x73\x74\x20\x3d\x20\x69\x70\x36\x2e\
-\x64\x61\x64\x64\x72\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x6c\x34\x5f\x70\x72\
-\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x20\x69\x70\x36\x2e\x6e\x65\x78\x74\x68\x64\
-\x72\x3b\0\x20\x20\x20\x20\x73\x77\x69\x74\x63\x68\x20\x28\x68\x64\x72\x5f\x74\
-\x79\x70\x65\x29\x20\x7b\0\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x69\x70\
-\x76\x36\x5f\x6f\x70\x74\x5f\x68\x64\x72\x20\x65\x78\x74\x5f\x68\x64\x72\x20\
-\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\
-\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\
-\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x2a\x6c\x34\x5f\x6f\
-\x66\x66\x73\x65\x74\x2c\x20\x26\x65\x78\x74\x5f\x68\x64\x72\x2c\0\x20\x20\x20\
-\x20\x20\x20\x20\x20\x69\x66\x20\x28\x2a\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\
-\x6f\x6c\x20\x3d\x3d\x20\x49\x50\x50\x52\x4f\x54\x4f\x5f\x52\x4f\x55\x54\x49\
-\x4e\x47\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\
-\x72\x75\x63\x74\x20\x69\x70\x76\x36\x5f\x72\x74\x5f\x68\x64\x72\x20\x65\x78\
-\x74\x5f\x72\x74\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\
-\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\
-\x6b\x62\x2c\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x65\x78\
-\x74\x5f\x72\x74\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\
-\x20\x28\x28\x65\x78\x74\x5f\x72\x74\x2e\x74\x79\x70\x65\x20\x3d\x3d\x20\x49\
-\x50\x56\x36\x5f\x53\x52\x43\x52\x54\x5f\x54\x59\x50\x45\x5f\x32\x29\x20\x26\
-\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x20\x6f\x66\x66\x73\
-\x65\x74\x6f\x66\x28\x73\x74\x72\x75\x63\x74\x20\x72\x74\x32\x5f\x68\x64\x72\
-\x2c\x20\x61\x64\x64\x72\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x47\
+\x50\x4c\x20\x76\x32\0\0\x9f\xeb\x01\0\x18\0\0\0\0\0\0\0\x50\x05\0\0\x50\x05\0\
+\0\x8e\x11\0\0\0\0\0\0\0\0\0\x02\x03\0\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\
+\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x02\0\0\0\x05\0\0\0\0\0\0\
+\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\x02\x06\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\
+\x02\0\0\0\x04\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\x02\x08\0\0\0\0\0\0\0\0\0\0\x03\0\
+\0\0\0\x02\0\0\0\x04\0\0\0\x0a\0\0\0\0\0\0\0\0\0\0\x02\x0a\0\0\0\0\0\0\0\0\0\0\
+\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x01\0\0\0\0\0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\
+\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0\x27\0\0\0\x07\0\0\0\x80\0\
+\0\0\x32\0\0\0\x09\0\0\0\xc0\0\0\0\x3e\0\0\0\0\0\0\x0e\x0b\0\0\0\x01\0\0\0\0\0\
+\0\0\0\0\0\x02\x0e\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x28\0\0\
+\0\0\0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\
+\0\x40\0\0\0\x27\0\0\0\x0d\0\0\0\x80\0\0\0\x32\0\0\0\x09\0\0\0\xc0\0\0\0\x59\0\
+\0\0\0\0\0\x0e\x0f\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x12\0\0\0\0\0\0\0\0\0\0\
+\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x80\0\0\0\0\0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\
+\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0\x27\0\0\0\x01\0\0\0\x80\0\
+\0\0\x32\0\0\0\x11\0\0\0\xc0\0\0\0\x72\0\0\0\0\0\0\x0e\x13\0\0\0\x01\0\0\0\0\0\
+\0\0\0\0\0\x02\x16\0\0\0\x90\0\0\0\x25\0\0\x04\xc8\0\0\0\x9a\0\0\0\x17\0\0\0\0\
+\0\0\0\x9e\0\0\0\x17\0\0\0\x20\0\0\0\xa7\0\0\0\x17\0\0\0\x40\0\0\0\xac\0\0\0\
+\x17\0\0\0\x60\0\0\0\xba\0\0\0\x17\0\0\0\x80\0\0\0\xc3\0\0\0\x17\0\0\0\xa0\0\0\
+\0\xd0\0\0\0\x17\0\0\0\xc0\0\0\0\xd9\0\0\0\x17\0\0\0\xe0\0\0\0\xe4\0\0\0\x17\0\
+\0\0\0\x01\0\0\xed\0\0\0\x17\0\0\0\x20\x01\0\0\xfd\0\0\0\x17\0\0\0\x40\x01\0\0\
+\x05\x01\0\0\x17\0\0\0\x60\x01\0\0\x0e\x01\0\0\x19\0\0\0\x80\x01\0\0\x11\x01\0\
+\0\x17\0\0\0\x20\x02\0\0\x16\x01\0\0\x17\0\0\0\x40\x02\0\0\x21\x01\0\0\x17\0\0\
+\0\x60\x02\0\0\x26\x01\0\0\x17\0\0\0\x80\x02\0\0\x2f\x01\0\0\x17\0\0\0\xa0\x02\
+\0\0\x37\x01\0\0\x17\0\0\0\xc0\x02\0\0\x3e\x01\0\0\x17\0\0\0\xe0\x02\0\0\x49\
+\x01\0\0\x17\0\0\0\0\x03\0\0\x53\x01\0\0\x1a\0\0\0\x20\x03\0\0\x5e\x01\0\0\x1a\
+\0\0\0\xa0\x03\0\0\x68\x01\0\0\x17\0\0\0\x20\x04\0\0\x74\x01\0\0\x17\0\0\0\x40\
+\x04\0\0\x7f\x01\0\0\x17\0\0\0\x60\x04\0\0\0\0\0\0\x1b\0\0\0\x80\x04\0\0\x89\
+\x01\0\0\x1d\0\0\0\xc0\x04\0\0\x90\x01\0\0\x17\0\0\0\0\x05\0\0\x99\x01\0\0\x17\
+\0\0\0\x20\x05\0\0\0\0\0\0\x1f\0\0\0\x40\x05\0\0\xa2\x01\0\0\x17\0\0\0\x80\x05\
+\0\0\xab\x01\0\0\x21\0\0\0\xa0\x05\0\0\xb7\x01\0\0\x1d\0\0\0\xc0\x05\0\0\xc0\
+\x01\0\0\x17\0\0\0\0\x06\0\0\xd0\x01\0\0\x23\0\0\0\x20\x06\0\0\xe1\x01\0\0\x23\
+\0\0\0\x30\x06\0\0\xf0\x01\0\0\0\0\0\x08\x18\0\0\0\xf6\x01\0\0\0\0\0\x01\x04\0\
+\0\0\x20\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x17\0\0\0\x04\0\0\0\x05\0\0\0\0\0\0\0\
+\0\0\0\x03\0\0\0\0\x17\0\0\0\x04\0\0\0\x04\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\
+\x03\x02\0\0\x1c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x2c\0\0\0\x0d\x02\0\0\0\0\0\
+\x08\x1e\0\0\0\x13\x02\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\0\0\0\0\x01\0\0\x05\
+\x08\0\0\0\x26\x02\0\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x2d\0\0\0\x29\x02\0\
+\0\0\0\0\x08\x22\0\0\0\x2e\x02\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\0\x3c\x02\0\0\0\
+\0\0\x08\x24\0\0\0\x42\x02\0\0\0\0\0\x01\x02\0\0\0\x10\0\0\0\0\0\0\0\x01\0\0\
+\x0d\x02\0\0\0\x51\x02\0\0\x15\0\0\0\x55\x02\0\0\x01\0\0\x0c\x25\0\0\0\x5b\x11\
+\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x27\0\0\0\x04\0\
+\0\0\x07\0\0\0\x60\x11\0\0\0\0\0\x0e\x28\0\0\0\x01\0\0\0\x69\x11\0\0\x03\0\0\
+\x0f\0\0\0\0\x0c\0\0\0\0\0\0\0\x20\0\0\0\x10\0\0\0\0\0\0\0\x20\0\0\0\x14\0\0\0\
+\0\0\0\0\x20\0\0\0\x6f\x11\0\0\x01\0\0\x0f\0\0\0\0\x29\0\0\0\0\0\0\0\x07\0\0\0\
+\x77\x11\0\0\0\0\0\x07\0\0\0\0\x85\x11\0\0\0\0\0\x07\0\0\0\0\0\x69\x6e\x74\0\
+\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\0\
+\x74\x79\x70\x65\0\x6b\x65\x79\x5f\x73\x69\x7a\x65\0\x76\x61\x6c\x75\x65\x5f\
+\x73\x69\x7a\x65\0\x6d\x61\x78\x5f\x65\x6e\x74\x72\x69\x65\x73\0\x74\x61\x70\
+\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x63\x6f\x6e\x66\x69\x67\x75\x72\x61\x74\
+\x69\x6f\x6e\x73\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x74\x6f\x65\
+\x70\x6c\x69\x74\x7a\x5f\x6b\x65\x79\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\
+\x70\x5f\x69\x6e\x64\x69\x72\x65\x63\x74\x69\x6f\x6e\x5f\x74\x61\x62\x6c\x65\0\
+\x5f\x5f\x73\x6b\x5f\x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\x79\
+\x70\x65\0\x6d\x61\x72\x6b\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\
+\x67\0\x70\x72\x6f\x74\x6f\x63\x6f\x6c\0\x76\x6c\x61\x6e\x5f\x70\x72\x65\x73\
+\x65\x6e\x74\0\x76\x6c\x61\x6e\x5f\x74\x63\x69\0\x76\x6c\x61\x6e\x5f\x70\x72\
+\x6f\x74\x6f\0\x70\x72\x69\x6f\x72\x69\x74\x79\0\x69\x6e\x67\x72\x65\x73\x73\
+\x5f\x69\x66\x69\x6e\x64\x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\
+\x69\x6e\x64\x65\x78\0\x63\x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\
+\x73\x69\x64\0\x64\x61\x74\x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\
+\x69\x5f\x69\x64\0\x66\x61\x6d\x69\x6c\x79\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\
+\x70\x34\0\x6c\x6f\x63\x61\x6c\x5f\x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\
+\x69\x70\x36\0\x6c\x6f\x63\x61\x6c\x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\
+\x5f\x70\x6f\x72\x74\0\x6c\x6f\x63\x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\
+\x61\x5f\x6d\x65\x74\x61\0\x74\x73\x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\
+\x65\x6e\0\x67\x73\x6f\x5f\x73\x65\x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\
+\x74\x73\x74\x61\x6d\x70\x5f\x74\x79\x70\x65\0\x68\x77\x74\x73\x74\x61\x6d\x70\
+\0\x76\x6e\x65\x74\x5f\x68\x61\x73\x68\x5f\x76\x61\x6c\x75\x65\0\x76\x6e\x65\
+\x74\x5f\x68\x61\x73\x68\x5f\x72\x65\x70\x6f\x72\x74\0\x76\x6e\x65\x74\x5f\x72\
+\x73\x73\x5f\x71\x75\x65\x75\x65\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\
+\x6e\x65\x64\x20\x69\x6e\x74\0\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x5f\x5f\
+\x75\x36\x34\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\
+\x6e\x67\0\x73\x6b\0\x5f\x5f\x75\x38\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x63\
+\x68\x61\x72\0\x5f\x5f\x75\x31\x36\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x73\
+\x68\x6f\x72\x74\0\x73\x6b\x62\0\x74\x75\x6e\x5f\x72\x73\x73\x5f\x73\x74\x65\
+\x65\x72\x69\x6e\x67\x5f\x70\x72\x6f\x67\0\x73\x6f\x63\x6b\x65\x74\0\x2f\x68\
+\x6f\x6d\x65\x2f\x61\x6c\x61\x72\x6d\x2f\x71\x2f\x76\x61\x72\x2f\x71\x65\x6d\
+\x75\x2f\x74\x6f\x6f\x6c\x73\x2f\x65\x62\x70\x66\x2f\x72\x73\x73\x2e\x62\x70\
+\x66\x2e\x63\0\x69\x6e\x74\x20\x74\x75\x6e\x5f\x72\x73\x73\x5f\x73\x74\x65\x65\
+\x72\x69\x6e\x67\x5f\x70\x72\x6f\x67\x28\x73\x74\x72\x75\x63\x74\x20\x5f\x5f\
+\x73\x6b\x5f\x62\x75\x66\x66\x20\x2a\x73\x6b\x62\x29\0\x20\x20\x20\x20\x5f\x5f\
+\x75\x33\x32\x20\x6b\x65\x79\x20\x3d\x20\x30\x3b\0\x20\x20\x20\x20\x63\x6f\x6e\
+\x66\x69\x67\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\
+\x70\x5f\x65\x6c\x65\x6d\x28\x26\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\
+\x5f\x63\x6f\x6e\x66\x69\x67\x75\x72\x61\x74\x69\x6f\x6e\x73\x2c\x20\x26\x6b\
+\x65\x79\x29\x3b\0\x20\x20\x20\x20\x74\x6f\x65\x20\x3d\x20\x62\x70\x66\x5f\x6d\
+\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x74\x61\x70\
+\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x74\x6f\x65\x70\x6c\x69\x74\x7a\x5f\x6b\
+\x65\x79\x2c\x20\x26\x6b\x65\x79\x29\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\x63\
+\x6f\x6e\x66\x69\x67\x20\x26\x26\x20\x74\x6f\x65\x29\x20\x7b\0\x20\x20\x20\x20\
+\x20\x20\x20\x20\x69\x66\x20\x28\x21\x63\x6f\x6e\x66\x69\x67\x2d\x3e\x72\x65\
+\x64\x69\x72\x65\x63\x74\x29\x20\x7b\0\x20\x20\x20\x20\x5f\x5f\x75\x38\x20\x72\
+\x73\x73\x5f\x69\x6e\x70\x75\x74\x5b\x48\x41\x53\x48\x5f\x43\x41\x4c\x43\x55\
+\x4c\x41\x54\x49\x4f\x4e\x5f\x42\x55\x46\x46\x45\x52\x5f\x53\x49\x5a\x45\x5d\
+\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x70\x61\
+\x63\x6b\x65\x74\x5f\x68\x61\x73\x68\x5f\x69\x6e\x66\x6f\x5f\x74\x20\x70\x61\
+\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\
+\x69\x66\x20\x28\x21\x69\x6e\x66\x6f\x20\x7c\x7c\x20\x21\x73\x6b\x62\x29\x20\
+\x7b\0\x20\x20\x20\x20\x5f\x5f\x62\x65\x31\x36\x20\x72\x65\x74\x20\x3d\x20\x30\
+\x3b\0\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\
 \x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\
-\x28\x73\x6b\x62\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x69\x66\x20\x28\x65\x72\x72\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x69\
-\x70\x76\x36\x5f\x65\x78\x74\x5f\x64\x73\x74\x20\x3d\x20\x31\x3b\0\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x5f\x5f\x61\x74\x74\x72\x69\x62\
-\x75\x74\x65\x5f\x5f\x28\x28\x70\x61\x63\x6b\x65\x64\x29\x29\x20\x6f\x70\x74\
-\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x3d\x20\x28\x6f\
-\x70\x74\x2e\x74\x79\x70\x65\x20\x3d\x3d\x20\x49\x50\x56\x36\x5f\x54\x4c\x56\
-\x5f\x50\x41\x44\x31\x29\x20\x3f\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x69\x66\x20\x28\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\
-\x20\x2b\x20\x31\x20\x3e\x3d\x20\x65\x78\x74\x5f\x68\x64\x72\x2e\x68\x64\x72\
-\x6c\x65\x6e\x20\x2a\x20\x38\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x28\x73\x6b\x62\x2c\x20\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x72\x65\x74\x2c\
+\x20\x73\x69\x7a\x65\x6f\x66\x28\x72\x65\x74\x29\x2c\0\x20\x20\x20\x20\x69\x66\
+\x20\x28\x65\x72\x72\x29\x20\x7b\0\x20\x20\x20\x20\x73\x77\x69\x74\x63\x68\x20\
+\x28\x62\x70\x66\x5f\x6e\x74\x6f\x68\x73\x28\x72\x65\x74\x29\x29\x20\x7b\0\x20\
 \x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\
 \x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\
-\x76\x65\x28\x73\x6b\x62\x2c\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\
-\x2b\x20\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\x2c\0\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x6f\x70\x74\x2e\x74\
-\x79\x70\x65\x20\x3d\x3d\x20\x49\x50\x56\x36\x5f\x54\x4c\x56\x5f\x48\x41\x4f\
-\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\
-\x2b\x20\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\0\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\
-\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\
-\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\0\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\
-\x72\x72\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x69\x70\x76\x36\
-\x5f\x65\x78\x74\x5f\x73\x72\x63\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x66\x72\x61\x67\
-\x6d\x65\x6e\x74\x65\x64\x20\x3d\x20\x74\x72\x75\x65\x3b\0\x20\x20\x20\x20\x20\
-\x20\x20\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x3d\x20\x28\x65\
-\x78\x74\x5f\x68\x64\x72\x2e\x68\x64\x72\x6c\x65\x6e\x20\x2b\x20\x31\x29\x20\
-\x2a\x20\x38\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x2a\x6c\x34\x5f\x70\x72\x6f\
-\x74\x6f\x63\x6f\x6c\x20\x3d\x20\x65\x78\x74\x5f\x68\x64\x72\x2e\x6e\x65\x78\
-\x74\x68\x64\x72\x3b\0\x20\x20\x20\x20\x66\x6f\x72\x20\x28\x75\x6e\x73\x69\x67\
-\x6e\x65\x64\x20\x69\x6e\x74\x20\x69\x20\x3d\x20\x30\x3b\x20\x69\x20\x3c\x20\
-\x49\x50\x36\x5f\x45\x58\x54\x45\x4e\x53\x49\x4f\x4e\x53\x5f\x43\x4f\x55\x4e\
-\x54\x3b\x20\x2b\x2b\x69\x29\x20\x7b\0\x20\x20\x20\x20\x7d\x20\x65\x6c\x73\x65\
-\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\
-\x5f\x69\x70\x76\x36\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\
-\x5f\x69\x70\x76\x36\x5f\x65\x78\x74\x5f\x64\x73\x74\x20\x26\x26\0\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\
-\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\x69\x70\x76\x36\x5f\x65\x78\x74\x5f\x73\
-\x72\x63\x20\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x65\x6c\x73\x65\
-\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\
-\x5f\x75\x64\x70\x20\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x65\x6c\
-\x73\x65\x20\x69\x66\x20\x28\x63\x6f\x6e\x66\x69\x67\x2d\x3e\x68\x61\x73\x68\
-\x5f\x74\x79\x70\x65\x73\x20\x26\x20\x56\x49\x52\x54\x49\x4f\x5f\x4e\x45\x54\
-\x5f\x52\x53\x53\x5f\x48\x41\x53\x48\x5f\x54\x59\x50\x45\x5f\x49\x50\x76\x34\
-\x29\x20\x7b\0\x20\x20\x20\x20\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x5f\x6d\x65\
-\x6d\x63\x70\x79\x28\x26\x72\x73\x73\x5f\x69\x6e\x70\x75\x74\x5b\x2a\x62\x79\
-\x74\x65\x73\x5f\x77\x72\x69\x74\x74\x65\x6e\x5d\x2c\x20\x70\x74\x72\x2c\x20\
-\x73\x69\x7a\x65\x29\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\
-\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x75\x64\x70\x20\x3d\x20\x31\x3b\0\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x75\x64\x70\
-\x68\x64\x72\x20\x75\x64\x70\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\
+\x76\x65\x28\x73\x6b\x62\x2c\x20\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x72\x65\
+\x74\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\x72\x65\x74\x29\x2c\0\x20\x20\x20\x20\
+\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x74\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\
+\x6c\x33\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x3d\x20\x30\x29\x20\x7b\0\
+\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x69\x70\
+\x76\x34\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x72\x75\
+\x63\x74\x20\x69\x70\x68\x64\x72\x20\x69\x70\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\
 \x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\
 \x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\
-\x65\x28\x73\x6b\x62\x2c\x20\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\
-\x75\x64\x70\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\x75\x64\x70\x29\x2c\0\x20\x20\
-\x20\x20\x20\x20\x20\x20\x7d\x20\x65\x6c\x73\x65\x20\x69\x66\x20\x28\x63\x6f\
-\x6e\x66\x69\x67\x2d\x3e\x68\x61\x73\x68\x5f\x74\x79\x70\x65\x73\x20\x26\x20\
-\x56\x49\x52\x54\x49\x4f\x5f\x4e\x45\x54\x5f\x52\x53\x53\x5f\x48\x41\x53\x48\
-\x5f\x54\x59\x50\x45\x5f\x49\x50\x76\x36\x29\x20\x7b\0\x20\x20\x20\x20\x66\x6f\
-\x72\x20\x28\x62\x79\x74\x65\x20\x3d\x20\x30\x3b\x20\x62\x79\x74\x65\x20\x3c\
-\x20\x48\x41\x53\x48\x5f\x43\x41\x4c\x43\x55\x4c\x41\x54\x49\x4f\x4e\x5f\x42\
-\x55\x46\x46\x45\x52\x5f\x53\x49\x5a\x45\x3b\x20\x62\x79\x74\x65\x2b\x2b\x29\
-\x20\x7b\0\x20\x20\x20\x20\x5f\x5f\x75\x33\x32\x20\x6c\x65\x66\x74\x6d\x6f\x73\
-\x74\x5f\x33\x32\x5f\x62\x69\x74\x73\x20\x3d\x20\x6b\x65\x79\x2d\x3e\x6c\x65\
-\x66\x74\x6d\x6f\x73\x74\x5f\x33\x32\x5f\x62\x69\x74\x73\x3b\0\x20\x20\x20\x20\
-\x20\x20\x20\x20\x5f\x5f\x75\x38\x20\x69\x6e\x70\x75\x74\x5f\x62\x79\x74\x65\
-\x20\x3d\x20\x69\x6e\x70\x75\x74\x5b\x62\x79\x74\x65\x5d\x3b\0\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x69\x6e\x70\x75\x74\x5f\x62\
-\x79\x74\x65\x20\x26\x20\x28\x31\x20\x3c\x3c\x20\x37\x29\x29\x20\x7b\0\x20\x20\
-\x20\x20\x20\x20\x20\x20\x5f\x5f\x75\x38\x20\x6b\x65\x79\x5f\x62\x79\x74\x65\
-\x20\x3d\x20\x6b\x65\x79\x2d\x3e\x6e\x65\x78\x74\x5f\x62\x79\x74\x65\x5b\x62\
-\x79\x74\x65\x5d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x28\x6c\x65\x66\x74\x6d\x6f\x73\x74\x5f\x33\x32\x5f\
-\x62\x69\x74\x73\x20\x3c\x3c\x20\x31\x29\x20\x7c\x20\x28\x28\x6b\x65\x79\x5f\
-\x62\x79\x74\x65\x20\x26\x20\x28\x31\x20\x3c\x3c\x20\x37\x29\x29\x20\x3e\x3e\
-\x20\x37\x29\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x5f\x75\
-\x33\x32\x20\x74\x61\x62\x6c\x65\x5f\x69\x64\x78\x20\x3d\x20\x68\x61\x73\x68\
-\x20\x25\x20\x63\x6f\x6e\x66\x69\x67\x2d\x3e\x69\x6e\x64\x69\x72\x65\x63\x74\
-\x69\x6f\x6e\x73\x5f\x6c\x65\x6e\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x71\x75\x65\x75\x65\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\
-\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x74\x61\x70\x5f\x72\x73\x73\
-\x5f\x6d\x61\x70\x5f\x69\x6e\x64\x69\x72\x65\x63\x74\x69\x6f\x6e\x5f\x74\x61\
-\x62\x6c\x65\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\
-\x28\x71\x75\x65\x75\x65\x29\x20\x7b\0\x7d\0\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x2a\x71\x75\x65\
-\x75\x65\x3b\0\x63\x68\x61\x72\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\
-\x70\x73\0\x6c\x69\x63\x65\x6e\x73\x65\0\x62\x70\x66\x5f\x66\x6c\x6f\x77\x5f\
-\x6b\x65\x79\x73\0\x62\x70\x66\x5f\x73\x6f\x63\x6b\0\0\0\x9f\xeb\x01\0\x20\0\0\
-\0\0\0\0\0\x14\0\0\0\x14\0\0\0\x8c\x0c\0\0\xa0\x0c\0\0\0\0\0\0\x08\0\0\0\x6b\
-\x02\0\0\x01\0\0\0\0\0\0\0\x26\0\0\0\x10\0\0\0\x6b\x02\0\0\xc8\0\0\0\0\0\0\0\
-\x72\x02\0\0\x9e\x02\0\0\0\x5c\x08\0\x10\0\0\0\x72\x02\0\0\xcf\x02\0\0\x0b\x74\
-\x08\0\x20\0\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x28\0\0\0\x72\x02\0\0\xe2\x02\0\0\
-\x0e\x80\x08\0\x50\0\0\0\x72\x02\0\0\x27\x03\0\0\x0b\x84\x08\0\x88\0\0\0\x72\
-\x02\0\0\x67\x03\0\0\x10\x8c\x08\0\x90\0\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x98\0\
-\0\0\x72\x02\0\0\x67\x03\0\0\x10\x8c\x08\0\xa0\0\0\0\x72\x02\0\0\x80\x03\0\0\
-\x16\x90\x08\0\xa8\0\0\0\x72\x02\0\0\x80\x03\0\0\x0d\x90\x08\0\xc0\0\0\0\x72\
-\x02\0\0\xa1\x03\0\0\x0a\x04\x06\0\xe8\0\0\0\x72\x02\0\0\xd8\x03\0\0\x1f\x10\
-\x06\0\x38\x01\0\0\x72\x02\0\0\x08\x04\0\0\x0f\xa0\x04\0\x40\x01\0\0\x72\x02\0\
-\0\x21\x04\0\0\x0c\x20\x04\0\x50\x01\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x58\x01\0\
-\0\x72\x02\0\0\x35\x04\0\0\x0b\x2c\x04\0\x80\x01\0\0\x72\x02\0\0\x7b\x04\0\0\
-\x09\x34\x04\0\x90\x01\0\0\x72\x02\0\0\x7b\x04\0\0\x09\x34\x04\0\xa0\x01\0\0\
-\x72\x02\0\0\x8a\x04\0\0\x0d\x44\x04\0\xb8\x01\0\0\x72\x02\0\0\x8a\x04\0\0\x05\
-\x44\x04\0\xd8\x01\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\xe0\x01\0\0\x72\x02\0\0\xa8\
-\x04\0\0\x0f\x58\x04\0\0\x02\0\0\x72\x02\0\0\x7b\x04\0\0\x09\x70\x04\0\x10\x02\
-\0\0\x72\x02\0\0\x7b\x04\0\0\x09\x70\x04\0\x18\x02\0\0\x72\x02\0\0\xf2\x04\0\0\
-\x0c\x80\x04\0\x20\x02\0\0\x72\x02\0\0\x02\x05\0\0\x09\xbc\x04\0\x50\x02\0\0\
-\x72\x02\0\0\x1e\x05\0\0\x17\xd4\x04\0\x60\x02\0\0\x72\x02\0\0\x39\x05\0\0\x16\
-\xdc\x04\0\x80\x02\0\0\x72\x02\0\0\x1e\x05\0\0\x17\xd4\x04\0\x88\x02\0\0\x72\
-\x02\0\0\x57\x05\0\0\x0f\xe0\x04\0\xb0\x02\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\xe8\
-\x04\0\xc0\x02\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\xe8\x04\0\xc8\x02\0\0\x72\x02\0\
-\0\xad\x05\0\0\x24\0\x05\0\xd0\x02\0\0\x72\x02\0\0\xad\x05\0\0\x20\0\x05\0\xe0\
-\x02\0\0\x72\x02\0\0\xda\x05\0\0\x1b\xf8\x04\0\xe8\x02\0\0\x72\x02\0\0\xda\x05\
-\0\0\x16\xf8\x04\0\xf0\x02\0\0\x72\x02\0\0\xfb\x05\0\0\x1b\xfc\x04\0\xf8\x02\0\
-\0\x72\x02\0\0\xfb\x05\0\0\x16\xfc\x04\0\0\x03\0\0\x72\x02\0\0\x1c\x06\0\0\x1a\
-\x08\x05\0\x08\x03\0\0\x72\x02\0\0\xad\x05\0\0\x1d\0\x05\0\x10\x03\0\0\x72\x02\
-\0\0\x3f\x06\0\0\x18\x0c\x05\0\x18\x03\0\0\x72\x02\0\0\x3f\x06\0\0\x1c\x0c\x05\
-\0\x30\x03\0\0\x72\x02\0\0\x5f\x06\0\0\x15\x68\x05\0\x40\x03\0\0\x72\x02\0\0\
-\x5f\x06\0\0\x1a\x68\x05\0\x58\x03\0\0\x72\x02\0\0\x93\x06\0\0\x0d\x6c\x05\0\
-\x78\x03\0\0\x72\x02\0\0\xbd\x06\0\0\x1a\x70\x05\0\x88\x03\0\0\x72\x02\0\0\xdb\
-\x06\0\0\x1b\x78\x05\0\xa8\x03\0\0\x72\x02\0\0\xbd\x06\0\0\x1a\x70\x05\0\xb0\
-\x03\0\0\x72\x02\0\0\xff\x06\0\0\x13\x7c\x05\0\xd8\x03\0\0\x72\x02\0\0\x50\x07\
-\0\0\x11\x84\x05\0\xe8\x03\0\0\x72\x02\0\0\x50\x07\0\0\x11\x84\x05\0\xf0\x03\0\
-\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x10\x04\0\0\x72\x02\0\0\x67\x07\0\0\x15\x2c\x06\
-\0\x18\x04\0\0\x72\x02\0\0\x67\x07\0\0\x09\x2c\x06\0\x20\x04\0\0\x72\x02\0\0\0\
-\0\0\0\0\0\0\0\x70\x04\0\0\x72\x02\0\0\x86\x07\0\0\x19\x30\x06\0\x80\x04\0\0\
-\x72\x02\0\0\x86\x07\0\0\x20\x30\x06\0\xa0\x04\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\
-\xf0\x04\0\0\x72\x02\0\0\xa8\x07\0\0\x17\x14\x05\0\0\x05\0\0\x72\x02\0\0\xc3\
-\x07\0\0\x18\x1c\x05\0\x30\x05\0\0\x72\x02\0\0\xa8\x07\0\0\x17\x14\x05\0\x48\
-\x05\0\0\x72\x02\0\0\xe4\x07\0\0\x0f\x20\x05\0\x70\x05\0\0\x72\x02\0\0\x9a\x05\
-\0\0\x0d\x28\x05\0\x80\x05\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\x28\x05\0\x88\x05\0\
-\0\x72\x02\0\0\x29\x08\0\0\x1d\x38\x05\0\xc8\x05\0\0\x72\x02\0\0\x4c\x08\0\0\
-\x1d\x3c\x05\0\x08\x06\0\0\x72\x02\0\0\x6f\x08\0\0\x1b\x44\x05\0\x10\x06\0\0\
-\x72\x02\0\0\x92\x08\0\0\x05\x30\x02\0\x58\x06\0\0\x72\x02\0\0\xaa\x08\0\0\x19\
-\xb8\x02\0\xd0\x06\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\xd8\x06\0\0\x72\x02\0\0\xd0\
-\x08\0\0\x0f\xc8\x02\0\0\x07\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\xd0\x02\0\x18\x07\
-\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\xd0\x02\0\x20\x07\0\0\x72\x02\0\0\x15\x09\0\0\
-\x0d\xe0\x02\0\x40\x07\0\0\x72\x02\0\0\x44\x09\0\0\x20\xe4\x02\0\x68\x07\0\0\
-\x72\x02\0\0\x70\x09\0\0\x13\xec\x02\0\x90\x07\0\0\x72\x02\0\0\x50\x07\0\0\x11\
-\xf4\x02\0\xa8\x07\0\0\x72\x02\0\0\x50\x07\0\0\x11\xf4\x02\0\xb0\x07\0\0\x72\
-\x02\0\0\xb8\x09\0\0\x19\x04\x03\0\xb8\x07\0\0\x72\x02\0\0\xb8\x09\0\0\x34\x04\
-\x03\0\xe0\x07\0\0\x72\x02\0\0\xee\x09\0\0\x15\x18\x03\0\xf0\x07\0\0\x72\x02\0\
-\0\x2f\x0a\0\0\x17\x14\x03\0\x18\x08\0\0\x72\x02\0\0\x66\x0a\0\0\x15\x24\x03\0\
-\x30\x08\0\0\x72\x02\0\0\x66\x0a\0\0\x15\x24\x03\0\x38\x08\0\0\x72\x02\0\0\x81\
-\x0a\0\0\x27\x34\x03\0\x70\x08\0\0\x72\x02\0\0\xac\x0a\0\0\x27\x50\x03\0\x80\
-\x08\0\0\x72\x02\0\0\xdc\x0a\0\0\x1c\xb4\x03\0\x88\x08\0\0\x72\x02\0\0\x18\x0b\
-\0\0\x20\xc0\x03\0\x98\x08\0\0\x72\x02\0\0\x18\x0b\0\0\x2f\xc0\x03\0\xa0\x08\0\
-\0\x72\x02\0\0\x18\x0b\0\0\x36\xc0\x03\0\xa8\x08\0\0\x72\x02\0\0\x18\x0b\0\0\
-\x15\xc0\x03\0\x18\x09\0\0\x72\x02\0\0\x54\x0b\0\0\x43\x64\x03\0\x38\x09\0\0\
-\x72\x02\0\0\0\0\0\0\0\0\0\0\x40\x09\0\0\x72\x02\0\0\x54\x0b\0\0\x17\x64\x03\0\
-\x68\x09\0\0\x72\x02\0\0\x66\x0a\0\0\x15\x6c\x03\0\x80\x09\0\0\x72\x02\0\0\x66\
-\x0a\0\0\x15\x6c\x03\0\x88\x09\0\0\x72\x02\0\0\xa4\x0b\0\0\x19\x7c\x03\0\x90\
-\x09\0\0\x72\x02\0\0\xa4\x0b\0\0\x15\x7c\x03\0\x98\x09\0\0\x72\x02\0\0\xd4\x0b\
-\0\0\x19\x84\x03\0\xa0\x09\0\0\x72\x02\0\0\x04\x0c\0\0\x1b\x80\x03\0\xd0\x09\0\
-\0\x72\x02\0\0\x3f\x0c\0\0\x19\x94\x03\0\xe8\x09\0\0\x72\x02\0\0\x3f\x0c\0\0\
-\x19\x94\x03\0\xf0\x09\0\0\x72\x02\0\0\x5e\x0c\0\0\x2b\xa4\x03\0\x10\x0a\0\0\
-\x72\x02\0\0\xdc\x0a\0\0\x1f\xb4\x03\0\x30\x0a\0\0\x72\x02\0\0\x8d\x0c\0\0\x21\
-\xd4\x03\0\x40\x0a\0\0\x72\x02\0\0\xb5\x0c\0\0\x20\xe4\x03\0\x48\x0a\0\0\x72\
-\x02\0\0\xb5\x0c\0\0\x2c\xe4\x03\0\x60\x0a\0\0\x72\x02\0\0\xb5\x0c\0\0\x14\xe4\
-\x03\0\x70\x0a\0\0\x72\x02\0\0\xe5\x0c\0\0\x20\xe0\x03\0\x80\x0a\0\0\x72\x02\0\
-\0\x92\x08\0\0\x05\x30\x02\0\xb0\x0a\0\0\x72\x02\0\0\x0d\x0d\0\0\x38\xc0\x02\0\
-\xd0\x0a\0\0\x72\x02\0\0\x0d\x0d\0\0\x05\xc0\x02\0\xe8\x0a\0\0\x72\x02\0\0\x92\
-\x08\0\0\x05\x30\x02\0\xf8\x0a\0\0\x72\x02\0\0\x4b\x0d\0\0\x1c\xc8\x06\0\x08\
-\x0b\0\0\x72\x02\0\0\x4b\x0d\0\0\x10\xc8\x06\0\x10\x0b\0\0\x72\x02\0\0\0\0\0\0\
-\0\0\0\0\x60\x0b\0\0\x72\x02\0\0\x86\x07\0\0\x19\xcc\x06\0\x68\x0b\0\0\x72\x02\
-\0\0\x86\x07\0\0\x20\xcc\x06\0\xa0\x0b\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\x04\x07\
-\0\xb0\x0b\0\0\x72\x02\0\0\x71\x0d\0\0\x1d\x04\x07\0\xb8\x0b\0\0\x72\x02\0\0\
-\x71\x0d\0\0\x2d\x04\x07\0\xc8\x0b\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\xd8\x06\0\
-\xf8\x0b\0\0\x72\x02\0\0\xa0\x0d\0\0\x1d\xd8\x06\0\x08\x0c\0\0\x72\x02\0\0\xa0\
-\x0d\0\0\x2d\xd8\x06\0\x18\x0c\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\xe8\x0c\0\0\x72\
-\x02\0\0\xcf\x0d\0\0\x20\x6c\x06\0\xf0\x0c\0\0\x72\x02\0\0\xcf\x0d\0\0\x27\x6c\
-\x06\0\x18\x0d\0\0\x72\x02\0\0\xf8\x0d\0\0\x27\xa8\x06\0\x20\x0d\0\0\x72\x02\0\
-\0\xf8\x0d\0\0\x14\xa8\x06\0\x28\x0d\0\0\x72\x02\0\0\x41\x0e\0\0\x05\x98\x01\0\
-\x38\x0d\0\0\x72\x02\0\0\x41\x0e\0\0\x05\x98\x01\0\x60\x0d\0\0\x72\x02\0\0\x9a\
-\x05\0\0\x0d\x54\x05\0\x70\x0d\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x80\x0d\0\0\x72\
-\x02\0\0\xcf\x0d\0\0\x20\x48\x07\0\x88\x0d\0\0\x72\x02\0\0\xcf\x0d\0\0\x27\x48\
-\x07\0\xc0\x0d\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\x80\x07\0\xd0\x0d\0\0\x72\x02\0\
-\0\x71\x0d\0\0\x1d\x80\x07\0\xd8\x0d\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\x80\x07\0\
-\xe8\x0d\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\x54\x07\0\x18\x0e\0\0\x72\x02\0\0\xa0\
-\x0d\0\0\x1d\x54\x07\0\x28\x0e\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\x54\x07\0\x40\
-\x0e\0\0\x72\x02\0\0\x7e\x0e\0\0\x1a\xa0\x05\0\x50\x0e\0\0\x72\x02\0\0\x9c\x0e\
-\0\0\x1b\xa8\x05\0\x60\x0e\0\0\x72\x02\0\0\x7e\x0e\0\0\x1a\xa0\x05\0\x68\x0e\0\
-\0\x72\x02\0\0\xc0\x0e\0\0\x13\xac\x05\0\x90\x0e\0\0\x72\x02\0\0\x50\x07\0\0\
-\x11\xb4\x05\0\xa0\x0e\0\0\x72\x02\0\0\x50\x07\0\0\x11\xb4\x05\0\xb0\x0e\0\0\
-\x72\x02\0\0\x92\x08\0\0\x05\x30\x02\0\xc0\x0e\0\0\x72\x02\0\0\x11\x0f\0\0\x27\
-\xcc\x07\0\xd0\x0e\0\0\x72\x02\0\0\x11\x0f\0\0\x14\xcc\x07\0\xf0\x0e\0\0\x72\
-\x02\0\0\xa0\x0d\0\0\x2d\xd0\x07\0\0\x0f\0\0\x72\x02\0\0\xa0\x0d\0\0\x1d\xd0\
-\x07\0\x08\x0f\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\xd0\x07\0\x30\x0f\0\0\x72\x02\0\
-\0\0\0\0\0\0\0\0\0\x80\x0f\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x90\x0f\0\0\x72\x02\
-\0\0\x71\x0d\0\0\x1d\xfc\x07\0\x98\x0f\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\xfc\x07\
-\0\xa8\x0f\0\0\x72\x02\0\0\x41\x0e\0\0\x05\x98\x01\0\xf8\x0f\0\0\x72\x02\0\0\
-\x41\x0e\0\0\x05\x98\x01\0\x30\x10\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x40\x10\0\0\
-\x72\x02\0\0\x5a\x0f\0\0\x05\xd0\x01\0\x48\x10\0\0\x72\x02\0\0\x9c\x0f\0\0\x23\
-\xc4\x01\0\x60\x10\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x68\x10\0\0\x72\x02\0\0\xd0\
-\x0f\0\0\x1b\xd4\x01\0\x88\x10\0\0\x72\x02\0\0\xf7\x0f\0\0\x11\xe8\x01\0\xa0\
-\x10\0\0\x72\x02\0\0\x20\x10\0\0\x19\xd8\x01\0\xb8\x10\0\0\x72\x02\0\0\x4e\x10\
-\0\0\x27\xfc\x01\0\xd0\x10\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\xd8\x10\0\
-\0\x72\x02\0\0\xf7\x0f\0\0\x11\xe8\x01\0\x18\x11\0\0\x72\x02\0\0\x4e\x10\0\0\
-\x27\xfc\x01\0\x20\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\x28\x11\0\0\
-\x72\x02\0\0\xf7\x0f\0\0\x11\xe8\x01\0\x50\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x27\
-\xfc\x01\0\x70\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\x78\x11\0\0\x72\
-\x02\0\0\xf7\x0f\0\0\x11\xe8\x01\0\xa0\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\
-\x01\0\xc0\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\xc8\x11\0\0\x72\x02\0\
-\0\xf7\x0f\0\0\x11\xe8\x01\0\x08\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\
-\x10\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\x18\x12\0\0\x72\x02\0\0\xf7\
-\x0f\0\0\x11\xe8\x01\0\x58\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\x60\
-\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\x68\x12\0\0\x72\x02\0\0\xf7\x0f\
-\0\0\x11\xe8\x01\0\xa8\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\xb0\x12\0\
-\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\xb8\x12\0\0\x72\x02\0\0\xf7\x0f\0\0\
-\x11\xe8\x01\0\xe0\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\xe8\x12\0\0\
-\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\xf0\x12\0\0\x72\x02\0\0\x5a\x0f\0\0\x3d\
-\xd0\x01\0\0\x13\0\0\x72\x02\0\0\x5a\x0f\0\0\x05\xd0\x01\0\x10\x13\0\0\x72\x02\
-\0\0\x9a\x10\0\0\x2e\xa4\x08\0\x30\x13\0\0\x72\x02\0\0\x9a\x10\0\0\x24\xa4\x08\
-\0\x48\x13\0\0\x72\x02\0\0\x9a\x10\0\0\x13\xa4\x08\0\x58\x13\0\0\x72\x02\0\0\0\
-\0\0\0\0\0\0\0\x60\x13\0\0\x72\x02\0\0\xd9\x10\0\0\x15\xb0\x08\0\x78\x13\0\0\
-\x72\x02\0\0\x21\x11\0\0\x11\xbc\x08\0\x80\x13\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\
-\xa0\x13\0\0\x72\x02\0\0\x3a\x11\0\0\x01\xe0\x08\0\xa8\x13\0\0\x72\x02\0\0\x3c\
-\x11\0\0\x18\xc0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\x03\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x25\x01\0\0\0\0\x03\0\xa0\x13\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\x78\x01\0\0\0\0\x03\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\x4e\x01\0\0\0\0\x03\0\x80\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xbd\0\0\0\0\0\x03\
-\0\xd0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2a\x02\0\0\0\0\x03\0\x20\x02\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\xfc\0\0\0\0\0\x03\0\xe8\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x43\
-\x02\0\0\0\0\x03\0\x10\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1d\x01\0\0\0\0\x03\0\
-\xe0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1a\x02\0\0\0\0\x03\0\x30\x03\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\x12\x02\0\0\0\0\x03\0\x38\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd4\
-\0\0\0\0\0\x03\0\xf0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x0a\x02\0\0\0\0\x03\0\xf8\
-\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x3e\x01\0\0\0\0\x03\0\xe8\x0c\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\x57\x01\0\0\0\0\x03\0\xa0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd0\x01\
-\0\0\0\0\x03\0\x38\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7f\x01\0\0\0\0\x03\0\x78\
-\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x53\x02\0\0\0\0\x03\0\xb0\x0e\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\xe9\x01\0\0\0\0\x03\0\x50\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xc8\x01\
-\0\0\0\0\x03\0\xc0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb0\x01\0\0\0\0\x03\0\x60\
-\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x8f\x01\0\0\0\0\x03\0\x60\x08\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\x5f\x01\0\0\0\0\x03\0\x30\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x46\x01\
-\0\0\0\0\x03\0\x40\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xe1\x01\0\0\0\0\x03\0\xe8\
-\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xc0\x01\0\0\0\0\x03\0\x48\x08\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\x67\x01\0\0\0\0\x03\0\x18\x09\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x22\x02\
-\0\0\0\0\x03\0\x80\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb8\x01\0\0\0\0\x03\0\xf8\
-\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x87\x01\0\0\0\0\x03\0\x50\x0d\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\xe4\0\0\0\0\0\x03\0\x08\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x15\x01\0\
-\0\0\0\x03\0\xe8\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xdc\0\0\0\0\0\x03\0\xb0\x0a\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\x4b\x02\0\0\0\0\x03\0\xd8\x0a\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\xa8\x01\0\0\0\0\x03\0\x80\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x36\x01\0\0\0\
-\0\x03\0\xb0\x0b\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf4\0\0\0\0\0\x03\0\xc8\x0b\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\x3b\x02\0\0\0\0\x03\0\xf8\x0b\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\xd9\x01\0\0\0\0\x03\0\x18\x0c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x02\0\0\0\0\
-\x03\0\x10\x0c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xcc\0\0\0\0\0\x03\0\x18\x0d\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\xa0\x01\0\0\0\0\x03\0\xc0\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\x0d\x01\0\0\0\0\x03\0\xd0\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xc4\0\0\0\0\0\x03\0\
-\xe8\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xfa\x01\0\0\0\0\x03\0\x18\x0e\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\x2e\x01\0\0\0\0\x03\0\0\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xec\0\
-\0\0\0\0\x03\0\x18\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x32\x02\0\0\0\0\x03\0\xf8\
-\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf1\x01\0\0\0\0\x03\0\x30\x10\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\x97\x01\0\0\0\0\x03\0\x58\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x6f\x01\
-\0\0\0\0\x03\0\x10\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\x01\0\0\0\0\x03\0\xa8\
-\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x59\0\0\0\x12\0\x03\0\0\0\0\0\0\0\0\0\xb8\x13\
+\x65\x28\x73\x6b\x62\x2c\x20\x30\x2c\x20\x26\x69\x70\x2c\x20\x73\x69\x7a\x65\
+\x6f\x66\x28\x69\x70\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\
+\x65\x72\x72\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\
+\x3e\x69\x73\x5f\x66\x72\x61\x67\x6d\x65\x6e\x74\x65\x64\x20\x3d\x20\x21\x21\
+\x69\x70\x2e\x66\x72\x61\x67\x5f\x6f\x66\x66\x3b\0\x20\x20\x20\x20\x20\x20\x20\
+\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x6e\x5f\x73\x72\x63\x20\x3d\x20\x69\x70\x2e\
+\x73\x61\x64\x64\x72\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\
+\x3e\x69\x6e\x5f\x64\x73\x74\x20\x3d\x20\x69\x70\x2e\x64\x61\x64\x64\x72\x3b\0\
+\x20\x20\x20\x20\x20\x20\x20\x20\x6c\x34\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\
+\x20\x3d\x20\x69\x70\x2e\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x3b\0\x20\x20\x20\x20\
+\x20\x20\x20\x20\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x3d\x20\x69\x70\x2e\
+\x69\x68\x6c\x20\x2a\x20\x34\x3b\0\x20\x20\x20\x20\x69\x66\x20\x28\x6c\x34\x5f\
+\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x21\x3d\x20\x30\x20\x26\x26\x20\x21\x69\
+\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x66\x72\x61\x67\x6d\x65\x6e\x74\x65\x64\x29\
+\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x6c\x34\x5f\x70\x72\
+\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x3d\x20\x49\x50\x50\x52\x4f\x54\x4f\x5f\x54\
+\x43\x50\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\
+\x66\x6f\x2d\x3e\x69\x73\x5f\x74\x63\x70\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\x20\x74\x63\x70\x68\
+\x64\x72\x20\x74\x63\x70\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\
+\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\
+\x28\x73\x6b\x62\x2c\x20\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x74\
+\x63\x70\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\x74\x63\x70\x29\x2c\0\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x29\x20\x7b\0\
+\x20\x20\x20\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\
+\x2e\x69\x73\x5f\x69\x70\x76\x34\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\
+\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\
+\x74\x63\x70\x20\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\
+\x3e\x69\x73\x5f\x69\x70\x76\x36\x20\x3d\x20\x31\x3b\0\x20\x20\x20\x20\x20\x20\
+\x20\x20\x73\x74\x72\x75\x63\x74\x20\x69\x70\x76\x36\x68\x64\x72\x20\x69\x70\
+\x36\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\
+\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\
+\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x30\x2c\x20\
+\x26\x69\x70\x36\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\x69\x70\x36\x29\x2c\0\x20\
+\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x6e\x36\x5f\x73\x72\
+\x63\x20\x3d\x20\x69\x70\x36\x2e\x73\x61\x64\x64\x72\x3b\0\x20\x20\x20\x20\x20\
+\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x6e\x36\x5f\x64\x73\x74\x20\x3d\x20\
+\x69\x70\x36\x2e\x64\x61\x64\x64\x72\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x6c\
+\x34\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x20\x69\x70\x36\x2e\x6e\x65\
+\x78\x74\x68\x64\x72\x3b\0\x20\x20\x20\x20\x73\x77\x69\x74\x63\x68\x20\x28\x68\
+\x64\x72\x5f\x74\x79\x70\x65\x29\x20\x7b\0\x20\x20\x20\x20\x73\x74\x72\x75\x63\
+\x74\x20\x69\x70\x76\x36\x5f\x6f\x70\x74\x5f\x68\x64\x72\x20\x65\x78\x74\x5f\
+\x68\x64\x72\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\
+\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\
+\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x2a\
+\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x2c\x20\x26\x65\x78\x74\x5f\x68\x64\x72\
+\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x2a\x6c\x34\x5f\x70\x72\
+\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x3d\x20\x49\x50\x50\x52\x4f\x54\x4f\x5f\x52\
+\x4f\x55\x54\x49\x4e\x47\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x73\x74\x72\x75\x63\x74\x20\x69\x70\x76\x36\x5f\x72\x74\x5f\x68\x64\
+\x72\x20\x65\x78\x74\x5f\x72\x74\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\
+\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\
+\x76\x65\x28\x73\x6b\x62\x2c\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x2c\
+\x20\x26\x65\x78\x74\x5f\x72\x74\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x69\x66\x20\x28\x28\x65\x78\x74\x5f\x72\x74\x2e\x74\x79\x70\x65\x20\
+\x3d\x3d\x20\x49\x50\x56\x36\x5f\x53\x52\x43\x52\x54\x5f\x54\x59\x50\x45\x5f\
+\x32\x29\x20\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\x20\
+\x6f\x66\x66\x73\x65\x74\x6f\x66\x28\x73\x74\x72\x75\x63\x74\x20\x72\x74\x32\
+\x5f\x68\x64\x72\x2c\x20\x61\x64\x64\x72\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\x5f\
+\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\x61\
+\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x29\x20\x7b\0\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\
+\x69\x73\x5f\x69\x70\x76\x36\x5f\x65\x78\x74\x5f\x64\x73\x74\x20\x3d\x20\x31\
+\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x5f\x5f\x61\x74\
+\x74\x72\x69\x62\x75\x74\x65\x5f\x5f\x28\x28\x70\x61\x63\x6b\x65\x64\x29\x29\
+\x20\x6f\x70\x74\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\
+\x3d\x20\x28\x6f\x70\x74\x2e\x74\x79\x70\x65\x20\x3d\x3d\x20\x49\x50\x56\x36\
+\x5f\x54\x4c\x56\x5f\x50\x41\x44\x31\x29\x20\x3f\0\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x6f\x70\x74\x5f\x6f\x66\
+\x66\x73\x65\x74\x20\x2b\x20\x31\x20\x3e\x3d\x20\x65\x78\x74\x5f\x68\x64\x72\
+\x2e\x68\x64\x72\x6c\x65\x6e\x20\x2a\x20\x38\x29\x20\x7b\0\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\
+\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\
+\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x2a\x6c\x34\x5f\x6f\x66\x66\
+\x73\x65\x74\x20\x2b\x20\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\x2c\0\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x6f\
+\x70\x74\x2e\x74\x79\x70\x65\x20\x3d\x3d\x20\x49\x50\x56\x36\x5f\x54\x4c\x56\
+\x5f\x48\x41\x4f\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2a\x6c\x34\x5f\x6f\x66\x66\
+\x73\x65\x74\x20\x2b\x20\x6f\x70\x74\x5f\x6f\x66\x66\x73\x65\x74\0\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\
+\x72\x20\x3d\x20\x62\x70\x66\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\
+\x74\x65\x73\x5f\x72\x65\x6c\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\0\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\
+\x66\x20\x28\x65\x72\x72\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\
+\x69\x70\x76\x36\x5f\x65\x78\x74\x5f\x73\x72\x63\x20\x3d\x20\x31\x3b\0\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\
+\x66\x72\x61\x67\x6d\x65\x6e\x74\x65\x64\x20\x3d\x20\x74\x72\x75\x65\x3b\0\x20\
+\x20\x20\x20\x20\x20\x20\x20\x2a\x6c\x34\x5f\x6f\x66\x66\x73\x65\x74\x20\x2b\
+\x3d\x20\x28\x65\x78\x74\x5f\x68\x64\x72\x2e\x68\x64\x72\x6c\x65\x6e\x20\x2b\
+\x20\x31\x29\x20\x2a\x20\x38\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x2a\x6c\x34\
+\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x20\x65\x78\x74\x5f\x68\x64\x72\
+\x2e\x6e\x65\x78\x74\x68\x64\x72\x3b\0\x20\x20\x20\x20\x66\x6f\x72\x20\x28\x75\
+\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\x20\x69\x20\x3d\x20\x30\x3b\x20\
+\x69\x20\x3c\x20\x49\x50\x36\x5f\x45\x58\x54\x45\x4e\x53\x49\x4f\x4e\x53\x5f\
+\x43\x4f\x55\x4e\x54\x3b\x20\x2b\x2b\x69\x29\x20\x7b\0\x20\x20\x20\x20\x7d\x20\
+\x65\x6c\x73\x65\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\
+\x6f\x2e\x69\x73\x5f\x69\x70\x76\x36\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\
+\x6f\x2e\x69\x73\x5f\x69\x70\x76\x36\x5f\x65\x78\x74\x5f\x64\x73\x74\x20\x26\
+\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x70\x61\
+\x63\x6b\x65\x74\x5f\x69\x6e\x66\x6f\x2e\x69\x73\x5f\x69\x70\x76\x36\x5f\x65\
+\x78\x74\x5f\x73\x72\x63\x20\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\
+\x65\x6c\x73\x65\x20\x69\x66\x20\x28\x70\x61\x63\x6b\x65\x74\x5f\x69\x6e\x66\
+\x6f\x2e\x69\x73\x5f\x75\x64\x70\x20\x26\x26\0\x20\x20\x20\x20\x20\x20\x20\x20\
+\x7d\x20\x65\x6c\x73\x65\x20\x69\x66\x20\x28\x63\x6f\x6e\x66\x69\x67\x2d\x3e\
+\x68\x61\x73\x68\x5f\x74\x79\x70\x65\x73\x20\x26\x20\x56\x49\x52\x54\x49\x4f\
+\x5f\x4e\x45\x54\x5f\x52\x53\x53\x5f\x48\x41\x53\x48\x5f\x54\x59\x50\x45\x5f\
+\x49\x50\x76\x34\x29\x20\x7b\0\x20\x20\x20\x20\x5f\x5f\x62\x75\x69\x6c\x74\x69\
+\x6e\x5f\x6d\x65\x6d\x63\x70\x79\x28\x26\x72\x73\x73\x5f\x69\x6e\x70\x75\x74\
+\x5b\x2a\x62\x79\x74\x65\x73\x5f\x77\x72\x69\x74\x74\x65\x6e\x5d\x2c\x20\x70\
+\x74\x72\x2c\x20\x73\x69\x7a\x65\x29\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x69\x6e\x66\x6f\x2d\x3e\x69\x73\x5f\x75\x64\x70\x20\x3d\x20\x31\
+\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x72\x75\x63\x74\
+\x20\x75\x64\x70\x68\x64\x72\x20\x75\x64\x70\x20\x3d\x20\x7b\x7d\x3b\0\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x65\x72\x72\x20\x3d\x20\x62\x70\x66\
+\x5f\x73\x6b\x62\x5f\x6c\x6f\x61\x64\x5f\x62\x79\x74\x65\x73\x5f\x72\x65\x6c\
+\x61\x74\x69\x76\x65\x28\x73\x6b\x62\x2c\x20\x6c\x34\x5f\x6f\x66\x66\x73\x65\
+\x74\x2c\x20\x26\x75\x64\x70\x2c\x20\x73\x69\x7a\x65\x6f\x66\x28\x75\x64\x70\
+\x29\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x65\x6c\x73\x65\x20\x69\x66\
+\x20\x28\x63\x6f\x6e\x66\x69\x67\x2d\x3e\x68\x61\x73\x68\x5f\x74\x79\x70\x65\
+\x73\x20\x26\x20\x56\x49\x52\x54\x49\x4f\x5f\x4e\x45\x54\x5f\x52\x53\x53\x5f\
+\x48\x41\x53\x48\x5f\x54\x59\x50\x45\x5f\x49\x50\x76\x36\x29\x20\x7b\0\x20\x20\
+\x20\x20\x66\x6f\x72\x20\x28\x62\x79\x74\x65\x20\x3d\x20\x30\x3b\x20\x62\x79\
+\x74\x65\x20\x3c\x20\x48\x41\x53\x48\x5f\x43\x41\x4c\x43\x55\x4c\x41\x54\x49\
+\x4f\x4e\x5f\x42\x55\x46\x46\x45\x52\x5f\x53\x49\x5a\x45\x3b\x20\x62\x79\x74\
+\x65\x2b\x2b\x29\x20\x7b\0\x20\x20\x20\x20\x5f\x5f\x75\x33\x32\x20\x6c\x65\x66\
+\x74\x6d\x6f\x73\x74\x5f\x33\x32\x5f\x62\x69\x74\x73\x20\x3d\x20\x6b\x65\x79\
+\x2d\x3e\x6c\x65\x66\x74\x6d\x6f\x73\x74\x5f\x33\x32\x5f\x62\x69\x74\x73\x3b\0\
+\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x5f\x75\x38\x20\x69\x6e\x70\x75\x74\x5f\
+\x62\x79\x74\x65\x20\x3d\x20\x69\x6e\x70\x75\x74\x5b\x62\x79\x74\x65\x5d\x3b\0\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x69\x6e\x70\
+\x75\x74\x5f\x62\x79\x74\x65\x20\x26\x20\x28\x31\x20\x3c\x3c\x20\x37\x29\x29\
+\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x5f\x75\x38\x20\x6b\x65\x79\x5f\
+\x62\x79\x74\x65\x20\x3d\x20\x6b\x65\x79\x2d\x3e\x6e\x65\x78\x74\x5f\x62\x79\
+\x74\x65\x5b\x62\x79\x74\x65\x5d\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x28\x6c\x65\x66\x74\x6d\x6f\x73\x74\
+\x5f\x33\x32\x5f\x62\x69\x74\x73\x20\x3c\x3c\x20\x31\x29\x20\x7c\x20\x28\x28\
+\x6b\x65\x79\x5f\x62\x79\x74\x65\x20\x26\x20\x28\x31\x20\x3c\x3c\x20\x37\x29\
+\x29\x20\x3e\x3e\x20\x37\x29\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x5f\x5f\x75\x33\x32\x20\x74\x61\x62\x6c\x65\x5f\x69\x64\x78\x20\x3d\x20\
+\x68\x61\x73\x68\x20\x25\x20\x63\x6f\x6e\x66\x69\x67\x2d\x3e\x69\x6e\x64\x69\
+\x72\x65\x63\x74\x69\x6f\x6e\x73\x5f\x6c\x65\x6e\x3b\0\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x71\x75\x65\x75\x65\x20\x3d\x20\x62\x70\x66\x5f\x6d\
+\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x74\x61\x70\
+\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x69\x6e\x64\x69\x72\x65\x63\x74\x69\x6f\
+\x6e\x5f\x74\x61\x62\x6c\x65\x2c\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x69\x66\x20\x28\x71\x75\x65\x75\x65\x29\x20\x7b\0\x7d\0\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\
+\x2a\x71\x75\x65\x75\x65\x3b\0\x63\x68\x61\x72\0\x5f\x6c\x69\x63\x65\x6e\x73\
+\x65\0\x2e\x6d\x61\x70\x73\0\x6c\x69\x63\x65\x6e\x73\x65\0\x62\x70\x66\x5f\x66\
+\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x62\x70\x66\x5f\x73\x6f\x63\x6b\0\0\0\x9f\
+\xeb\x01\0\x20\0\0\0\0\0\0\0\x14\0\0\0\x14\0\0\0\x8c\x0c\0\0\xa0\x0c\0\0\0\0\0\
+\0\x08\0\0\0\x6b\x02\0\0\x01\0\0\0\0\0\0\0\x26\0\0\0\x10\0\0\0\x6b\x02\0\0\xc8\
+\0\0\0\0\0\0\0\x72\x02\0\0\x9e\x02\0\0\0\x5c\x08\0\x10\0\0\0\x72\x02\0\0\xcf\
+\x02\0\0\x0b\x74\x08\0\x20\0\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x28\0\0\0\x72\x02\
+\0\0\xe2\x02\0\0\x0e\x80\x08\0\x50\0\0\0\x72\x02\0\0\x27\x03\0\0\x0b\x84\x08\0\
+\x78\0\0\0\x72\x02\0\0\x67\x03\0\0\x10\x8c\x08\0\x80\0\0\0\x72\x02\0\0\0\0\0\0\
+\0\0\0\0\x88\0\0\0\x72\x02\0\0\x67\x03\0\0\x10\x8c\x08\0\x90\0\0\0\x72\x02\0\0\
+\x80\x03\0\0\x16\x90\x08\0\x98\0\0\0\x72\x02\0\0\x80\x03\0\0\x0d\x90\x08\0\xb0\
+\0\0\0\x72\x02\0\0\xa1\x03\0\0\x0a\x04\x06\0\xd8\0\0\0\x72\x02\0\0\xd8\x03\0\0\
+\x1f\x10\x06\0\x30\x01\0\0\x72\x02\0\0\x08\x04\0\0\x0f\xa0\x04\0\x38\x01\0\0\
+\x72\x02\0\0\x21\x04\0\0\x0c\x20\x04\0\x48\x01\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\
+\x50\x01\0\0\x72\x02\0\0\x35\x04\0\0\x0b\x2c\x04\0\x78\x01\0\0\x72\x02\0\0\x7b\
+\x04\0\0\x09\x34\x04\0\x88\x01\0\0\x72\x02\0\0\x7b\x04\0\0\x09\x34\x04\0\x98\
+\x01\0\0\x72\x02\0\0\x8a\x04\0\0\x0d\x44\x04\0\xb0\x01\0\0\x72\x02\0\0\x8a\x04\
+\0\0\x05\x44\x04\0\xd0\x01\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\xd8\x01\0\0\x72\x02\
+\0\0\xa8\x04\0\0\x0f\x58\x04\0\xf8\x01\0\0\x72\x02\0\0\x7b\x04\0\0\x09\x70\x04\
+\0\x08\x02\0\0\x72\x02\0\0\x7b\x04\0\0\x09\x70\x04\0\x10\x02\0\0\x72\x02\0\0\
+\xf2\x04\0\0\x0c\x80\x04\0\x18\x02\0\0\x72\x02\0\0\x02\x05\0\0\x09\xbc\x04\0\
+\x40\x02\0\0\x72\x02\0\0\x1e\x05\0\0\x17\xd4\x04\0\x50\x02\0\0\x72\x02\0\0\x39\
+\x05\0\0\x16\xdc\x04\0\x70\x02\0\0\x72\x02\0\0\x1e\x05\0\0\x17\xd4\x04\0\x78\
+\x02\0\0\x72\x02\0\0\x57\x05\0\0\x0f\xe0\x04\0\xa0\x02\0\0\x72\x02\0\0\x9a\x05\
+\0\0\x0d\xe8\x04\0\xb0\x02\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\xe8\x04\0\xb8\x02\0\
+\0\x72\x02\0\0\xad\x05\0\0\x24\0\x05\0\xc0\x02\0\0\x72\x02\0\0\xad\x05\0\0\x20\
+\0\x05\0\xd0\x02\0\0\x72\x02\0\0\xda\x05\0\0\x1b\xf8\x04\0\xd8\x02\0\0\x72\x02\
+\0\0\xda\x05\0\0\x16\xf8\x04\0\xe0\x02\0\0\x72\x02\0\0\xfb\x05\0\0\x1b\xfc\x04\
+\0\xe8\x02\0\0\x72\x02\0\0\xfb\x05\0\0\x16\xfc\x04\0\xf0\x02\0\0\x72\x02\0\0\
+\x1c\x06\0\0\x1a\x08\x05\0\xf8\x02\0\0\x72\x02\0\0\xad\x05\0\0\x1d\0\x05\0\0\
+\x03\0\0\x72\x02\0\0\x3f\x06\0\0\x18\x0c\x05\0\x08\x03\0\0\x72\x02\0\0\x3f\x06\
+\0\0\x1c\x0c\x05\0\x20\x03\0\0\x72\x02\0\0\x5f\x06\0\0\x15\x68\x05\0\x30\x03\0\
+\0\x72\x02\0\0\x5f\x06\0\0\x1a\x68\x05\0\x48\x03\0\0\x72\x02\0\0\x93\x06\0\0\
+\x0d\x6c\x05\0\x68\x03\0\0\x72\x02\0\0\xbd\x06\0\0\x1a\x70\x05\0\x78\x03\0\0\
+\x72\x02\0\0\xdb\x06\0\0\x1b\x78\x05\0\x98\x03\0\0\x72\x02\0\0\xbd\x06\0\0\x1a\
+\x70\x05\0\xa0\x03\0\0\x72\x02\0\0\xff\x06\0\0\x13\x7c\x05\0\xc8\x03\0\0\x72\
+\x02\0\0\x50\x07\0\0\x11\x84\x05\0\xd8\x03\0\0\x72\x02\0\0\x50\x07\0\0\x11\x84\
+\x05\0\xe0\x03\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\x72\x02\0\0\x67\x07\0\
+\0\x15\x2c\x06\0\x08\x04\0\0\x72\x02\0\0\x67\x07\0\0\x09\x2c\x06\0\x10\x04\0\0\
+\x72\x02\0\0\0\0\0\0\0\0\0\0\x60\x04\0\0\x72\x02\0\0\x86\x07\0\0\x19\x30\x06\0\
+\x70\x04\0\0\x72\x02\0\0\x86\x07\0\0\x20\x30\x06\0\x90\x04\0\0\x72\x02\0\0\0\0\
+\0\0\0\0\0\0\xe0\x04\0\0\x72\x02\0\0\xa8\x07\0\0\x17\x14\x05\0\xf0\x04\0\0\x72\
+\x02\0\0\xc3\x07\0\0\x18\x1c\x05\0\x20\x05\0\0\x72\x02\0\0\xa8\x07\0\0\x17\x14\
+\x05\0\x30\x05\0\0\x72\x02\0\0\xe4\x07\0\0\x0f\x20\x05\0\x60\x05\0\0\x72\x02\0\
+\0\x9a\x05\0\0\x0d\x28\x05\0\x70\x05\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\x28\x05\0\
+\x78\x05\0\0\x72\x02\0\0\x29\x08\0\0\x1d\x38\x05\0\xb8\x05\0\0\x72\x02\0\0\x4c\
+\x08\0\0\x1d\x3c\x05\0\xf8\x05\0\0\x72\x02\0\0\x6f\x08\0\0\x1b\x44\x05\0\0\x06\
+\0\0\x72\x02\0\0\x92\x08\0\0\x05\x30\x02\0\x50\x06\0\0\x72\x02\0\0\xaa\x08\0\0\
+\x19\xb8\x02\0\xb8\x06\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\xc0\x06\0\0\x72\x02\0\0\
+\xd0\x08\0\0\x0f\xc8\x02\0\xe8\x06\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\xd0\x02\0\0\
+\x07\0\0\x72\x02\0\0\x9a\x05\0\0\x0d\xd0\x02\0\x08\x07\0\0\x72\x02\0\0\x15\x09\
+\0\0\x0d\xe0\x02\0\x28\x07\0\0\x72\x02\0\0\x44\x09\0\0\x20\xe4\x02\0\x50\x07\0\
+\0\x72\x02\0\0\x70\x09\0\0\x13\xec\x02\0\x78\x07\0\0\x72\x02\0\0\x50\x07\0\0\
+\x11\xf4\x02\0\x90\x07\0\0\x72\x02\0\0\x50\x07\0\0\x11\xf4\x02\0\x98\x07\0\0\
+\x72\x02\0\0\xb8\x09\0\0\x19\x04\x03\0\xa0\x07\0\0\x72\x02\0\0\xb8\x09\0\0\x34\
+\x04\x03\0\xc8\x07\0\0\x72\x02\0\0\xee\x09\0\0\x15\x18\x03\0\xd8\x07\0\0\x72\
+\x02\0\0\x2f\x0a\0\0\x17\x14\x03\0\0\x08\0\0\x72\x02\0\0\x66\x0a\0\0\x15\x24\
+\x03\0\x18\x08\0\0\x72\x02\0\0\x66\x0a\0\0\x15\x24\x03\0\x20\x08\0\0\x72\x02\0\
+\0\x81\x0a\0\0\x27\x34\x03\0\x48\x08\0\0\x72\x02\0\0\xac\x0a\0\0\x27\x50\x03\0\
+\x58\x08\0\0\x72\x02\0\0\xdc\x0a\0\0\x1c\xb4\x03\0\x60\x08\0\0\x72\x02\0\0\x18\
+\x0b\0\0\x20\xc0\x03\0\x70\x08\0\0\x72\x02\0\0\x18\x0b\0\0\x2f\xc0\x03\0\x78\
+\x08\0\0\x72\x02\0\0\x18\x0b\0\0\x36\xc0\x03\0\x80\x08\0\0\x72\x02\0\0\x18\x0b\
+\0\0\x15\xc0\x03\0\xe8\x08\0\0\x72\x02\0\0\x54\x0b\0\0\x43\x64\x03\0\x08\x09\0\
+\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x10\x09\0\0\x72\x02\0\0\x54\x0b\0\0\x17\x64\x03\
+\0\x38\x09\0\0\x72\x02\0\0\x66\x0a\0\0\x15\x6c\x03\0\x50\x09\0\0\x72\x02\0\0\
+\x66\x0a\0\0\x15\x6c\x03\0\x58\x09\0\0\x72\x02\0\0\xa4\x0b\0\0\x19\x7c\x03\0\
+\x60\x09\0\0\x72\x02\0\0\xa4\x0b\0\0\x15\x7c\x03\0\x68\x09\0\0\x72\x02\0\0\xd4\
+\x0b\0\0\x19\x84\x03\0\x70\x09\0\0\x72\x02\0\0\x04\x0c\0\0\x1b\x80\x03\0\xa0\
+\x09\0\0\x72\x02\0\0\x3f\x0c\0\0\x19\x94\x03\0\xb8\x09\0\0\x72\x02\0\0\x3f\x0c\
+\0\0\x19\x94\x03\0\xc0\x09\0\0\x72\x02\0\0\x5e\x0c\0\0\x2b\xa4\x03\0\xe0\x09\0\
+\0\x72\x02\0\0\xdc\x0a\0\0\x1f\xb4\x03\0\0\x0a\0\0\x72\x02\0\0\x8d\x0c\0\0\x21\
+\xd4\x03\0\x10\x0a\0\0\x72\x02\0\0\xb5\x0c\0\0\x20\xe4\x03\0\x18\x0a\0\0\x72\
+\x02\0\0\xb5\x0c\0\0\x2c\xe4\x03\0\x30\x0a\0\0\x72\x02\0\0\xb5\x0c\0\0\x14\xe4\
+\x03\0\x40\x0a\0\0\x72\x02\0\0\xe5\x0c\0\0\x20\xe0\x03\0\x48\x0a\0\0\x72\x02\0\
+\0\x92\x08\0\0\x05\x30\x02\0\x90\x0a\0\0\x72\x02\0\0\x0d\x0d\0\0\x38\xc0\x02\0\
+\xb0\x0a\0\0\x72\x02\0\0\x0d\x0d\0\0\x05\xc0\x02\0\xc8\x0a\0\0\x72\x02\0\0\x92\
+\x08\0\0\x05\x30\x02\0\xd8\x0a\0\0\x72\x02\0\0\x4b\x0d\0\0\x1c\xc8\x06\0\xe8\
+\x0a\0\0\x72\x02\0\0\x4b\x0d\0\0\x10\xc8\x06\0\xf0\x0a\0\0\x72\x02\0\0\0\0\0\0\
+\0\0\0\0\x40\x0b\0\0\x72\x02\0\0\x86\x07\0\0\x19\xcc\x06\0\x48\x0b\0\0\x72\x02\
+\0\0\x86\x07\0\0\x20\xcc\x06\0\x80\x0b\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\x04\x07\
+\0\x90\x0b\0\0\x72\x02\0\0\x71\x0d\0\0\x1d\x04\x07\0\x98\x0b\0\0\x72\x02\0\0\
+\x71\x0d\0\0\x2d\x04\x07\0\xa8\x0b\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\xd8\x06\0\
+\xd8\x0b\0\0\x72\x02\0\0\xa0\x0d\0\0\x1d\xd8\x06\0\xe8\x0b\0\0\x72\x02\0\0\xa0\
+\x0d\0\0\x2d\xd8\x06\0\xf8\x0b\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\xc8\x0c\0\0\x72\
+\x02\0\0\xcf\x0d\0\0\x20\x6c\x06\0\xd0\x0c\0\0\x72\x02\0\0\xcf\x0d\0\0\x27\x6c\
+\x06\0\xf8\x0c\0\0\x72\x02\0\0\xf8\x0d\0\0\x27\xa8\x06\0\0\x0d\0\0\x72\x02\0\0\
+\xf8\x0d\0\0\x14\xa8\x06\0\x08\x0d\0\0\x72\x02\0\0\x41\x0e\0\0\x05\x98\x01\0\
+\x18\x0d\0\0\x72\x02\0\0\x41\x0e\0\0\x05\x98\x01\0\x48\x0d\0\0\x72\x02\0\0\x9a\
+\x05\0\0\x0d\x54\x05\0\x58\x0d\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x68\x0d\0\0\x72\
+\x02\0\0\xcf\x0d\0\0\x20\x48\x07\0\x70\x0d\0\0\x72\x02\0\0\xcf\x0d\0\0\x27\x48\
+\x07\0\xa8\x0d\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\x80\x07\0\xb8\x0d\0\0\x72\x02\0\
+\0\x71\x0d\0\0\x1d\x80\x07\0\xc0\x0d\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\x80\x07\0\
+\xd0\x0d\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\x54\x07\0\0\x0e\0\0\x72\x02\0\0\xa0\
+\x0d\0\0\x1d\x54\x07\0\x10\x0e\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\x54\x07\0\x28\
+\x0e\0\0\x72\x02\0\0\x7e\x0e\0\0\x1a\xa0\x05\0\x38\x0e\0\0\x72\x02\0\0\x9c\x0e\
+\0\0\x1b\xa8\x05\0\x48\x0e\0\0\x72\x02\0\0\x7e\x0e\0\0\x1a\xa0\x05\0\x50\x0e\0\
+\0\x72\x02\0\0\xc0\x0e\0\0\x13\xac\x05\0\x78\x0e\0\0\x72\x02\0\0\x50\x07\0\0\
+\x11\xb4\x05\0\x88\x0e\0\0\x72\x02\0\0\x50\x07\0\0\x11\xb4\x05\0\x98\x0e\0\0\
+\x72\x02\0\0\x92\x08\0\0\x05\x30\x02\0\xa8\x0e\0\0\x72\x02\0\0\x11\x0f\0\0\x27\
+\xcc\x07\0\xb8\x0e\0\0\x72\x02\0\0\x11\x0f\0\0\x14\xcc\x07\0\xd8\x0e\0\0\x72\
+\x02\0\0\xa0\x0d\0\0\x2d\xd0\x07\0\xe8\x0e\0\0\x72\x02\0\0\xa0\x0d\0\0\x1d\xd0\
+\x07\0\xf0\x0e\0\0\x72\x02\0\0\xa0\x0d\0\0\x2d\xd0\x07\0\x18\x0f\0\0\x72\x02\0\
+\0\0\0\0\0\0\0\0\0\x68\x0f\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x78\x0f\0\0\x72\x02\
+\0\0\x71\x0d\0\0\x1d\xfc\x07\0\x80\x0f\0\0\x72\x02\0\0\x71\x0d\0\0\x2d\xfc\x07\
+\0\x90\x0f\0\0\x72\x02\0\0\x41\x0e\0\0\x05\x98\x01\0\xe0\x0f\0\0\x72\x02\0\0\
+\x41\x0e\0\0\x05\x98\x01\0\x18\x10\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x28\x10\0\0\
+\x72\x02\0\0\x5a\x0f\0\0\x05\xd0\x01\0\x30\x10\0\0\x72\x02\0\0\x9c\x0f\0\0\x23\
+\xc4\x01\0\x48\x10\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x50\x10\0\0\x72\x02\0\0\xd0\
+\x0f\0\0\x1b\xd4\x01\0\x70\x10\0\0\x72\x02\0\0\xf7\x0f\0\0\x11\xe8\x01\0\x88\
+\x10\0\0\x72\x02\0\0\x20\x10\0\0\x19\xd8\x01\0\xa0\x10\0\0\x72\x02\0\0\x4e\x10\
+\0\0\x27\xfc\x01\0\xb8\x10\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\xc0\x10\0\
+\0\x72\x02\0\0\xf7\x0f\0\0\x11\xe8\x01\0\0\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x27\
+\xfc\x01\0\x08\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\x10\x11\0\0\x72\
+\x02\0\0\xf7\x0f\0\0\x11\xe8\x01\0\x38\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\
+\x01\0\x58\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\x60\x11\0\0\x72\x02\0\
+\0\xf7\x0f\0\0\x11\xe8\x01\0\x88\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\
+\xa8\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\xb0\x11\0\0\x72\x02\0\0\xf7\
+\x0f\0\0\x11\xe8\x01\0\xf0\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\xf8\
+\x11\0\0\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\0\x12\0\0\x72\x02\0\0\xf7\x0f\0\
+\0\x11\xe8\x01\0\x40\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\x48\x12\0\0\
+\x72\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\x50\x12\0\0\x72\x02\0\0\xf7\x0f\0\0\x11\
+\xe8\x01\0\x90\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\x98\x12\0\0\x72\
+\x02\0\0\x4e\x10\0\0\x2d\xfc\x01\0\xa0\x12\0\0\x72\x02\0\0\xf7\x0f\0\0\x11\xe8\
+\x01\0\xc8\x12\0\0\x72\x02\0\0\x4e\x10\0\0\x27\xfc\x01\0\xd0\x12\0\0\x72\x02\0\
+\0\x4e\x10\0\0\x2d\xfc\x01\0\xd8\x12\0\0\x72\x02\0\0\x5a\x0f\0\0\x3d\xd0\x01\0\
+\xe8\x12\0\0\x72\x02\0\0\x5a\x0f\0\0\x05\xd0\x01\0\xf8\x12\0\0\x72\x02\0\0\x9a\
+\x10\0\0\x2e\xa4\x08\0\x18\x13\0\0\x72\x02\0\0\x9a\x10\0\0\x24\xa4\x08\0\x30\
+\x13\0\0\x72\x02\0\0\x9a\x10\0\0\x13\xa4\x08\0\x40\x13\0\0\x72\x02\0\0\0\0\0\0\
+\0\0\0\0\x48\x13\0\0\x72\x02\0\0\xd9\x10\0\0\x15\xb0\x08\0\x60\x13\0\0\x72\x02\
+\0\0\x21\x11\0\0\x11\xbc\x08\0\x68\x13\0\0\x72\x02\0\0\0\0\0\0\0\0\0\0\x88\x13\
+\0\0\x72\x02\0\0\x3a\x11\0\0\x01\xe0\x08\0\xa0\x13\0\0\x72\x02\0\0\x3c\x11\0\0\
+\x18\xc0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\
+\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x3d\x01\0\0\0\0\x03\0\x88\x13\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\x6f\x01\0\0\0\0\x03\0\xa8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x66\
+\x01\0\0\0\0\x03\0\x68\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xbd\0\0\0\0\0\x03\0\xc8\
+\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\0\0\0\0\x03\0\x18\x02\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\x04\x01\0\0\0\0\x03\0\xd8\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xcc\0\0\
+\0\0\0\x03\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1c\x01\0\0\0\0\x03\0\xd0\x02\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\x32\x02\0\0\0\0\x03\0\x20\x03\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\x2a\x02\0\0\0\0\x03\0\x20\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xec\0\0\0\0\0\
+\x03\0\xe0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x22\x02\0\0\0\0\x03\0\xd8\x0a\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\x56\x01\0\0\0\0\x03\0\xc8\x0c\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\x76\x01\0\0\0\0\x03\0\x90\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xe8\x01\0\0\0\0\
+\x03\0\x20\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x97\x01\0\0\0\0\x03\0\x60\x0d\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\x42\x02\0\0\0\0\x03\0\x98\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\xe0\x01\0\0\0\0\x03\0\x48\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xaf\x01\0\0\0\0\
+\x03\0\xb0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd0\x01\0\0\0\0\x03\0\x48\x0d\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\xa7\x01\0\0\0\0\x03\0\x38\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\x7e\x01\0\0\0\0\x03\0\0\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x5e\x01\0\0\0\0\x03\
+\0\x10\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf9\x01\0\0\0\0\x03\0\xd0\x0f\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\x86\x01\0\0\0\0\x03\0\xe8\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\x3a\x02\0\0\0\0\x03\0\x58\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd8\x01\0\0\0\0\x03\
+\0\xd0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x9f\x01\0\0\0\0\x03\0\x30\x0d\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\xfc\0\0\0\0\0\x03\0\xd8\x09\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x35\
+\x01\0\0\0\0\x03\0\xc8\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf4\0\0\0\0\0\x03\0\x88\
+\x0a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd4\0\0\0\0\0\x03\0\xb8\x0a\0\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\xc8\x01\0\0\0\0\x03\0\x68\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4e\x01\0\
+\0\0\0\x03\0\x90\x0b\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x14\x01\0\0\0\0\x03\0\xa8\x0b\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xc4\0\0\0\0\0\x03\0\xd8\x0b\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\xf1\x01\0\0\0\0\x03\0\xf8\x0b\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1a\x02\0\0\0\
+\0\x03\0\xf0\x0b\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xe4\0\0\0\0\0\x03\0\xf8\x0c\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\xc0\x01\0\0\0\0\x03\0\xa8\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\x2d\x01\0\0\0\0\x03\0\xb8\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xdc\0\0\0\0\0\x03\
+\0\xd0\x0d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x12\x02\0\0\0\0\x03\0\0\x0e\0\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\x46\x01\0\0\0\0\x03\0\xe8\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x0c\
+\x01\0\0\0\0\x03\0\0\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4a\x02\0\0\0\0\x03\0\xe0\
+\x0f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x09\x02\0\0\0\0\x03\0\x18\x10\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\xb7\x01\0\0\0\0\x03\0\x40\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x8e\x01\
+\0\0\0\0\x03\0\xf8\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x24\x01\0\0\0\0\x03\0\xa0\
+\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x59\0\0\0\x12\0\x03\0\0\0\0\0\0\0\0\0\xb0\x13\
 \0\0\0\0\0\0\x3e\0\0\0\x11\0\x05\0\0\0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\
 \x11\0\x05\0\x20\0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x86\0\0\0\x11\0\x05\0\x40\0\0\
 \0\0\0\0\0\x20\0\0\0\0\0\0\0\x7d\0\0\0\x11\0\x06\0\0\0\0\0\0\0\0\0\x07\0\0\0\0\
-\0\0\0\x28\0\0\0\0\0\0\0\x01\0\0\0\x36\0\0\0\x50\0\0\0\0\0\0\0\x01\0\0\0\x37\0\
-\0\0\x60\x13\0\0\0\0\0\0\x01\0\0\0\x38\0\0\0\x18\x05\0\0\0\0\0\0\x04\0\0\0\x36\
-\0\0\0\x24\x05\0\0\0\0\0\0\x04\0\0\0\x37\0\0\0\x30\x05\0\0\0\0\0\0\x04\0\0\0\
-\x38\0\0\0\x48\x05\0\0\0\0\0\0\x04\0\0\0\x39\0\0\0\x2c\0\0\0\0\0\0\0\x04\0\0\0\
+\0\0\0\x28\0\0\0\0\0\0\0\x01\0\0\0\x35\0\0\0\x50\0\0\0\0\0\0\0\x01\0\0\0\x36\0\
+\0\0\x48\x13\0\0\0\0\0\0\x01\0\0\0\x37\0\0\0\x18\x05\0\0\0\0\0\0\x04\0\0\0\x35\
+\0\0\0\x24\x05\0\0\0\0\0\0\x04\0\0\0\x36\0\0\0\x30\x05\0\0\0\0\0\0\x04\0\0\0\
+\x37\0\0\0\x48\x05\0\0\0\0\0\0\x04\0\0\0\x38\0\0\0\x2c\0\0\0\0\0\0\0\x04\0\0\0\
 \x01\0\0\0\x40\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x50\0\0\0\0\0\0\0\x04\0\0\0\
 \x01\0\0\0\x60\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x70\0\0\0\0\0\0\0\x04\0\0\0\
 \x01\0\0\0\x80\0\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x90\0\0\0\0\0\0\0\x04\0\0\0\
@@ -915,8 +914,8 @@ static inline const void *rss_bpf__elf_bytes(size_t *sz)
 \0\x01\0\0\0\x50\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x60\x0c\0\0\0\0\0\0\x04\0\
 \0\0\x01\0\0\0\x70\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x80\x0c\0\0\0\0\0\0\x04\
 \0\0\0\x01\0\0\0\x90\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\xa0\x0c\0\0\0\0\0\0\
-\x04\0\0\0\x01\0\0\0\xb0\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x3f\x40\x41\x42\
-\x43\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x74\x6f\x65\x70\x6c\x69\
+\x04\0\0\0\x01\0\0\0\xb0\x0c\0\0\0\0\0\0\x04\0\0\0\x01\0\0\0\x3e\x3f\x40\x41\
+\x42\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x74\x6f\x65\x70\x6c\x69\
 \x74\x7a\x5f\x6b\x65\x79\0\x2e\x74\x65\x78\x74\0\x2e\x72\x65\x6c\x2e\x42\x54\
 \x46\x2e\x65\x78\x74\0\x2e\x72\x65\x6c\x73\x6f\x63\x6b\x65\x74\0\x2e\x6d\x61\
 \x70\x73\0\x74\x61\x70\x5f\x72\x73\x73\x5f\x6d\x61\x70\x5f\x63\x6f\x6e\x66\x69\
@@ -926,50 +925,50 @@ static inline const void *rss_bpf__elf_bytes(size_t *sz)
 \x73\x73\x5f\x6d\x61\x70\x5f\x69\x6e\x64\x69\x72\x65\x63\x74\x69\x6f\x6e\x5f\
 \x74\x61\x62\x6c\x65\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\
 \x62\0\x2e\x72\x65\x6c\x2e\x42\x54\x46\0\x4c\x42\x42\x30\x5f\x39\0\x4c\x42\x42\
-\x30\x5f\x38\x39\0\x4c\x42\x42\x30\x5f\x36\x39\0\x4c\x42\x42\x30\x5f\x35\x39\0\
-\x4c\x42\x42\x30\x5f\x34\x39\0\x4c\x42\x42\x30\x5f\x33\x39\0\x4c\x42\x42\x30\
-\x5f\x39\x38\0\x4c\x42\x42\x30\x5f\x37\x38\0\x4c\x42\x42\x30\x5f\x31\x38\0\x4c\
-\x42\x42\x30\x5f\x31\x30\x38\0\x4c\x42\x42\x30\x5f\x38\x37\0\x4c\x42\x42\x30\
-\x5f\x34\x37\0\x4c\x42\x42\x30\x5f\x31\x37\0\x4c\x42\x42\x30\x5f\x31\x30\x37\0\
-\x4c\x42\x42\x30\x5f\x39\x36\0\x4c\x42\x42\x30\x5f\x37\x36\0\x4c\x42\x42\x30\
-\x5f\x36\x36\0\x4c\x42\x42\x30\x5f\x34\x36\0\x4c\x42\x42\x30\x5f\x31\x30\x36\0\
-\x4c\x42\x42\x30\x5f\x36\x35\0\x4c\x42\x42\x30\x5f\x34\x35\0\x4c\x42\x42\x30\
-\x5f\x33\x35\0\x4c\x42\x42\x30\x5f\x31\x30\x35\0\x4c\x42\x42\x30\x5f\x34\0\x4c\
-\x42\x42\x30\x5f\x35\x34\0\x4c\x42\x42\x30\x5f\x34\x34\0\x4c\x42\x42\x30\x5f\
-\x33\x34\0\x4c\x42\x42\x30\x5f\x31\x30\x34\0\x4c\x42\x42\x30\x5f\x39\x33\0\x4c\
-\x42\x42\x30\x5f\x38\x33\0\x4c\x42\x42\x30\x5f\x35\x33\0\x4c\x42\x42\x30\x5f\
-\x34\x33\0\x4c\x42\x42\x30\x5f\x33\x33\0\x4c\x42\x42\x30\x5f\x32\x33\0\x4c\x42\
-\x42\x30\x5f\x31\x30\x33\0\x4c\x42\x42\x30\x5f\x38\x32\0\x4c\x42\x42\x30\x5f\
-\x35\x32\0\x4c\x42\x42\x30\x5f\x32\x32\0\x4c\x42\x42\x30\x5f\x31\x30\x32\0\x4c\
-\x42\x42\x30\x5f\x39\x31\0\x4c\x42\x42\x30\x5f\x38\x31\0\x4c\x42\x42\x30\x5f\
-\x37\x31\0\x4c\x42\x42\x30\x5f\x36\x31\0\x4c\x42\x42\x30\x5f\x35\x31\0\x4c\x42\
-\x42\x30\x5f\x34\x31\0\x4c\x42\x42\x30\x5f\x31\x31\0\x4c\x42\x42\x30\x5f\x31\
-\x30\x31\0\x4c\x42\x42\x30\x5f\x38\x30\0\x4c\x42\x42\x30\x5f\x36\x30\0\x4c\x42\
-\x42\x30\x5f\x35\x30\0\x4c\x42\x42\x30\x5f\x32\x30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\xa4\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\x8d\x4a\0\0\0\0\0\0\x5b\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\x1a\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x31\0\
-\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\xb8\x13\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2d\0\0\0\x09\0\0\0\
-\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x88\x3d\0\0\0\0\0\0\x30\0\0\0\0\0\0\0\x0c\0\
-\0\0\x03\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x38\0\0\0\x01\0\0\0\x03\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\xf8\x13\0\0\0\0\0\0\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7e\0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\x58\x14\0\0\0\0\0\0\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\xb8\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x60\
-\x14\0\0\0\0\0\0\xf6\x16\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\xb4\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb8\x3d\0\0\0\0\
-\0\0\x40\0\0\0\0\0\0\0\x0c\0\0\0\x07\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\
-\x24\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x58\x2b\0\0\0\0\0\0\xc0\
-\x0c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x20\0\0\0\
-\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf8\x3d\0\0\0\0\0\0\x90\x0c\0\0\0\
-\0\0\0\x0c\0\0\0\x09\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x6f\0\0\0\x03\
-\x4c\xff\x6f\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\x88\x4a\0\0\0\0\0\0\x05\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xac\0\0\0\x02\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x18\x38\0\0\0\0\0\0\x70\x05\0\0\0\0\0\0\x01\0\0\
-\0\x35\0\0\0\x08\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0";
+\x30\x5f\x37\x39\0\x4c\x42\x42\x30\x5f\x35\x39\0\x4c\x42\x42\x30\x5f\x34\x39\0\
+\x4c\x42\x42\x30\x5f\x38\x38\0\x4c\x42\x42\x30\x5f\x36\x38\0\x4c\x42\x42\x30\
+\x5f\x35\x38\0\x4c\x42\x42\x30\x5f\x34\x38\0\x4c\x42\x42\x30\x5f\x33\x38\0\x4c\
+\x42\x42\x30\x5f\x31\x38\0\x4c\x42\x42\x30\x5f\x39\x37\0\x4c\x42\x42\x30\x5f\
+\x37\x37\0\x4c\x42\x42\x30\x5f\x31\x37\0\x4c\x42\x42\x30\x5f\x31\x30\x37\0\x4c\
+\x42\x42\x30\x5f\x38\x36\0\x4c\x42\x42\x30\x5f\x34\x36\0\x4c\x42\x42\x30\x5f\
+\x31\x30\x36\0\x4c\x42\x42\x30\x5f\x39\x35\0\x4c\x42\x42\x30\x5f\x37\x35\0\x4c\
+\x42\x42\x30\x5f\x36\x35\0\x4c\x42\x42\x30\x5f\x34\x35\0\x4c\x42\x42\x30\x5f\
+\x31\x30\x35\0\x4c\x42\x42\x30\x5f\x34\0\x4c\x42\x42\x30\x5f\x36\x34\0\x4c\x42\
+\x42\x30\x5f\x34\x34\0\x4c\x42\x42\x30\x5f\x33\x34\0\x4c\x42\x42\x30\x5f\x31\
+\x30\x34\0\x4c\x42\x42\x30\x5f\x35\x33\0\x4c\x42\x42\x30\x5f\x34\x33\0\x4c\x42\
+\x42\x30\x5f\x33\x33\0\x4c\x42\x42\x30\x5f\x32\x33\0\x4c\x42\x42\x30\x5f\x31\
+\x30\x33\0\x4c\x42\x42\x30\x5f\x39\x32\0\x4c\x42\x42\x30\x5f\x38\x32\0\x4c\x42\
+\x42\x30\x5f\x35\x32\0\x4c\x42\x42\x30\x5f\x34\x32\0\x4c\x42\x42\x30\x5f\x32\
+\x32\0\x4c\x42\x42\x30\x5f\x31\x30\x32\0\x4c\x42\x42\x30\x5f\x38\x31\0\x4c\x42\
+\x42\x30\x5f\x35\x31\0\x4c\x42\x42\x30\x5f\x31\x31\0\x4c\x42\x42\x30\x5f\x31\
+\x30\x31\0\x4c\x42\x42\x30\x5f\x39\x30\0\x4c\x42\x42\x30\x5f\x38\x30\0\x4c\x42\
+\x42\x30\x5f\x37\x30\0\x4c\x42\x42\x30\x5f\x36\x30\0\x4c\x42\x42\x30\x5f\x35\
+\x30\0\x4c\x42\x42\x30\x5f\x34\x30\0\x4c\x42\x42\x30\x5f\x32\x30\0\x4c\x42\x42\
+\x30\x5f\x31\x30\x30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xa4\0\
+\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x6d\x4a\0\0\0\0\0\0\x53\x02\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1a\0\0\0\x01\0\0\0\
+\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x31\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\xb0\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\x2d\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\x68\x3d\0\0\0\0\0\0\x30\0\0\0\0\0\0\0\x0c\0\0\0\x03\0\0\0\x08\0\0\0\0\0\0\0\
+\x10\0\0\0\0\0\0\0\x38\0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf0\
+\x13\0\0\0\0\0\0\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\x7e\0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x50\x14\0\0\0\0\0\
+\0\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb8\0\0\
+\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x58\x14\0\0\0\0\0\0\xf6\x16\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb4\0\0\0\x09\0\0\0\
+\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x98\x3d\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\x0c\0\
+\0\0\x07\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x24\0\0\0\x01\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\x50\x2b\0\0\0\0\0\0\xc0\x0c\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x20\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\xd8\x3d\0\0\0\0\0\0\x90\x0c\0\0\0\0\0\0\x0c\0\0\0\x09\0\0\0\x08\0\
+\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x6f\0\0\0\x03\x4c\xff\x6f\0\0\0\x80\0\0\0\0\0\0\
+\0\0\0\0\0\0\x68\x4a\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\xac\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\
+\x38\0\0\0\0\0\0\x58\x05\0\0\0\0\0\0\x01\0\0\0\x34\0\0\0\x08\0\0\0\0\0\0\0\x18\
+\0\0\0\0\0\0\0";
 }
 
 #ifdef __cplusplus
diff --git a/tools/ebpf/rss.bpf.c b/tools/ebpf/rss.bpf.c
index 9ec4bd2d91..22c75d5912 100644
--- a/tools/ebpf/rss.bpf.c
+++ b/tools/ebpf/rss.bpf.c
@@ -564,7 +564,7 @@ int tun_rss_steering_prog(struct __sk_buff *skb)
         return config->default_queue;
     }
 
-    return -1;
+    return 0;
 }
 
 char _license[] SEC("license") = "GPL v2";
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 20/21] ebpf: Refactor tun_rss_steering_prog()
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (18 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 19/21] ebpf: Return 0 when configuration fails Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  2023-10-30  5:12 ` [PATCH v6 21/21] ebpf: Add a separate target for skeleton Akihiko Odaki
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

This saves branches and makes later BPF program changes easier.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 tools/ebpf/rss.bpf.c | 26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/tools/ebpf/rss.bpf.c b/tools/ebpf/rss.bpf.c
index 22c75d5912..012af38df1 100644
--- a/tools/ebpf/rss.bpf.c
+++ b/tools/ebpf/rss.bpf.c
@@ -544,27 +544,23 @@ int tun_rss_steering_prog(struct __sk_buff *skb)
     config = bpf_map_lookup_elem(&tap_rss_map_configurations, &key);
     toe = bpf_map_lookup_elem(&tap_rss_map_toeplitz_key, &key);
 
-    if (config && toe) {
-        if (!config->redirect) {
-            return config->default_queue;
-        }
+    if (!config || !toe) {
+        return 0;
+    }
 
-        if (calculate_rss_hash(skb, config, toe, &hash)) {
-            __u32 table_idx = hash % config->indirections_len;
-            __u16 *queue = 0;
+    if (config->redirect && calculate_rss_hash(skb, config, toe, &hash)) {
+        __u32 table_idx = hash % config->indirections_len;
+        __u16 *queue = 0;
 
-            queue = bpf_map_lookup_elem(&tap_rss_map_indirection_table,
-                                        &table_idx);
+        queue = bpf_map_lookup_elem(&tap_rss_map_indirection_table,
+                                    &table_idx);
 
-            if (queue) {
-                return *queue;
-            }
+        if (queue) {
+            return *queue;
         }
-
-        return config->default_queue;
     }
 
-    return 0;
+    return config->default_queue;
 }
 
 char _license[] SEC("license") = "GPL v2";
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v6 21/21] ebpf: Add a separate target for skeleton
  2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
                   ` (19 preceding siblings ...)
  2023-10-30  5:12 ` [PATCH v6 20/21] ebpf: Refactor tun_rss_steering_prog() Akihiko Odaki
@ 2023-10-30  5:12 ` Akihiko Odaki
  20 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30  5:12 UTC (permalink / raw)
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Akihiko Odaki

This generalizes the rule to generate the skeleton and allows to add
another.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 tools/ebpf/Makefile.ebpf | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/tools/ebpf/Makefile.ebpf b/tools/ebpf/Makefile.ebpf
index 3391e7ce08..572ca5987a 100755
--- a/tools/ebpf/Makefile.ebpf
+++ b/tools/ebpf/Makefile.ebpf
@@ -1,23 +1,24 @@
-OBJS = rss.bpf.o
+SKELETONS = rss.bpf.skeleton.h
 
 LLVM_STRIP ?= llvm-strip
 CLANG ?= clang
 INC_FLAGS = `$(CLANG) -print-file-name=include`
 EXTRA_CFLAGS ?= -O2 -g -target bpf
 
-all: $(OBJS)
+all: $(SKELETONS)
 
 .PHONY: clean
 
 clean:
-	rm -f $(OBJS)
-	rm -f rss.bpf.skeleton.h
+	rm -f $(SKELETONS) $(SKELETONS:%.skeleton.h=%.o)
 
-$(OBJS):  %.o:%.c
+%.o: %.c
 	$(CLANG) $(INC_FLAGS) \
                 -D__KERNEL__ -D__ASM_SYSREG_H \
                 -I../include $(LINUXINCLUDE) \
                 $(EXTRA_CFLAGS) -c $< -o $@
 	$(LLVM_STRIP) -g $@
-	bpftool gen skeleton rss.bpf.o > rss.bpf.skeleton.h
-	cp rss.bpf.skeleton.h ../../ebpf/
+
+%.skeleton.h: %.o
+	bpftool gen skeleton $< > $@
+	cp $@ ../../ebpf/
-- 
2.42.0



^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-10-30  5:12 ` [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS Akihiko Odaki
@ 2023-10-30 12:14   ` Yuri Benditovich
  2023-10-30 12:21     ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Yuri Benditovich @ 2023-10-30 12:14 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: qemu-devel, Andrew Melnychenko, Michael S . Tsirkin, Jason Wang

[-- Attachment #1: Type: text/plain, Size: 5006 bytes --]

On Mon, Oct 30, 2023 at 7:14 AM Akihiko Odaki <akihiko.odaki@daynix.com>
wrote:

> vhost requires eBPF for RSS. When eBPF is not available, virtio-net
> implicitly disables RSS even if the user explicitly requests it. Return
> an error instead of implicitly disabling RSS if RSS is requested but not
> available.
>

I think that suggesting RSS feature when in fact it is not available is not
a good idea, this rather desinforms the guest.
Existing behavior (IMHO) makes more sense.
We can extend this discussion if needed, of course.


> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  hw/net/virtio-net.c | 97 ++++++++++++++++++++++-----------------------
>  1 file changed, 48 insertions(+), 49 deletions(-)
>
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 5d4afd12b2..7bb91617d0 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -792,9 +792,6 @@ static uint64_t virtio_net_get_features(VirtIODevice
> *vdev, uint64_t features,
>          return features;
>      }
>
> -    if (!ebpf_rss_is_loaded(&n->ebpf_rss)) {
> -        virtio_clear_feature(&features, VIRTIO_NET_F_RSS);
> -    }
>      features = vhost_net_get_features(get_vhost_net(nc->peer), features);
>      vdev->backend_features = features;
>
> @@ -3533,6 +3530,50 @@ static bool
> failover_hide_primary_device(DeviceListener *listener,
>      return qatomic_read(&n->failover_primary_hidden);
>  }
>
> +static void virtio_net_device_unrealize(DeviceState *dev)
> +{
> +    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> +    VirtIONet *n = VIRTIO_NET(dev);
> +    int i, max_queue_pairs;
> +
> +    if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) {
> +        virtio_net_unload_ebpf(n);
> +    }
> +
> +    /* This will stop vhost backend if appropriate. */
> +    virtio_net_set_status(vdev, 0);
> +
> +    g_free(n->netclient_name);
> +    n->netclient_name = NULL;
> +    g_free(n->netclient_type);
> +    n->netclient_type = NULL;
> +
> +    g_free(n->mac_table.macs);
> +    g_free(n->vlans);
> +
> +    if (n->failover) {
> +        qobject_unref(n->primary_opts);
> +        device_listener_unregister(&n->primary_listener);
> +        migration_remove_notifier(&n->migration_state);
> +    } else {
> +        assert(n->primary_opts == NULL);
> +    }
> +
> +    max_queue_pairs = n->multiqueue ? n->max_queue_pairs : 1;
> +    for (i = 0; i < max_queue_pairs; i++) {
> +        virtio_net_del_queue(n, i);
> +    }
> +    /* delete also control vq */
> +    virtio_del_queue(vdev, max_queue_pairs * 2);
> +    qemu_announce_timer_del(&n->announce_timer, false);
> +    g_free(n->vqs);
> +    qemu_del_nic(n->nic);
> +    virtio_net_rsc_cleanup(n);
> +    g_free(n->rss_data.indirections_table);
> +    net_rx_pkt_uninit(n->rx_pkt);
> +    virtio_cleanup(vdev);
> +}
> +
>  static void virtio_net_device_realize(DeviceState *dev, Error **errp)
>  {
>      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> @@ -3704,53 +3745,11 @@ static void virtio_net_device_realize(DeviceState
> *dev, Error **errp)
>
>      net_rx_pkt_init(&n->rx_pkt);
>
> -    if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) {
> -        virtio_net_load_ebpf(n);
> -    }
> -}
> -
> -static void virtio_net_device_unrealize(DeviceState *dev)
> -{
> -    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> -    VirtIONet *n = VIRTIO_NET(dev);
> -    int i, max_queue_pairs;
> -
> -    if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) {
> -        virtio_net_unload_ebpf(n);
> +    if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS) &&
> +        !virtio_net_load_ebpf(n)) {
> +        error_setg(errp, "Can't load eBPF RSS");
> +        virtio_net_device_unrealize(dev);
>      }
> -
> -    /* This will stop vhost backend if appropriate. */
> -    virtio_net_set_status(vdev, 0);
> -
> -    g_free(n->netclient_name);
> -    n->netclient_name = NULL;
> -    g_free(n->netclient_type);
> -    n->netclient_type = NULL;
> -
> -    g_free(n->mac_table.macs);
> -    g_free(n->vlans);
> -
> -    if (n->failover) {
> -        qobject_unref(n->primary_opts);
> -        device_listener_unregister(&n->primary_listener);
> -        migration_remove_notifier(&n->migration_state);
> -    } else {
> -        assert(n->primary_opts == NULL);
> -    }
> -
> -    max_queue_pairs = n->multiqueue ? n->max_queue_pairs : 1;
> -    for (i = 0; i < max_queue_pairs; i++) {
> -        virtio_net_del_queue(n, i);
> -    }
> -    /* delete also control vq */
> -    virtio_del_queue(vdev, max_queue_pairs * 2);
> -    qemu_announce_timer_del(&n->announce_timer, false);
> -    g_free(n->vqs);
> -    qemu_del_nic(n->nic);
> -    virtio_net_rsc_cleanup(n);
> -    g_free(n->rss_data.indirections_table);
> -    net_rx_pkt_uninit(n->rx_pkt);
> -    virtio_cleanup(vdev);
>  }
>
>  static void virtio_net_reset(VirtIODevice *vdev)
> --
> 2.42.0
>
>

[-- Attachment #2: Type: text/html, Size: 6264 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-10-30 12:14   ` Yuri Benditovich
@ 2023-10-30 12:21     ` Akihiko Odaki
  2023-10-30 12:51       ` Yuri Benditovich
  0 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30 12:21 UTC (permalink / raw)
  To: Yuri Benditovich
  Cc: qemu-devel, Andrew Melnychenko, Michael S . Tsirkin, Jason Wang

On 2023/10/30 21:14, Yuri Benditovich wrote:
> 
> 
> On Mon, Oct 30, 2023 at 7:14 AM Akihiko Odaki <akihiko.odaki@daynix.com 
> <mailto:akihiko.odaki@daynix.com>> wrote:
> 
>     vhost requires eBPF for RSS. When eBPF is not available, virtio-net
>     implicitly disables RSS even if the user explicitly requests it. Return
>     an error instead of implicitly disabling RSS if RSS is requested but not
>     available.
> 
> 
> I think that suggesting RSS feature when in fact it is not available is 
> not a good idea, this rather desinforms the guest.
> Existing behavior (IMHO) makes more sense.
> We can extend this discussion if needed, of course.

This change is not to advertise RSS when it's not available; it instead 
reports an error to the user.

For example, think of the following command line:
qemu-system-x86_64 -device virtio-net,rss=on,netdev=n -netdev user,id=n

Before this change, it gives no error and the user will not know RSS is 
not available. With this change it now gives an error as follows:
qemu-system-x86_64: -device virtio-net,rss=on,netdev=n: Can't load eBPF RSS


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 12/21] virtio-net: Enable software RSS
  2023-10-30  5:12 ` [PATCH v6 12/21] virtio-net: Enable software RSS Akihiko Odaki
@ 2023-10-30 12:42   ` Yuri Benditovich
  0 siblings, 0 replies; 59+ messages in thread
From: Yuri Benditovich @ 2023-10-30 12:42 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: qemu-devel, Andrew Melnychenko, Michael S . Tsirkin, Jason Wang

[-- Attachment #1: Type: text/plain, Size: 3672 bytes --]

On Mon, Oct 30, 2023 at 7:14 AM Akihiko Odaki <akihiko.odaki@daynix.com>
wrote:

> virtio-net implements software RSS but does not enable it. Enable it
> when RSS is requested, but the eBPF implementation is not available.
> We also check if vhost is in use in such a case since software RSS is
> incompatible with vhost. A warning will be emitted when falling back to
> software RSS since it provides no performance benefit.
>
>
Can you please elaborate what is wrong from your point of view in the
existing implementation?
In general it does (IMO) what you describe.
I'd like to note several things:
- The "vhost=off" is in fact the fallback mode (libvirt default is vhost=on)
- The main goal of software RSS was to provide a reference for RSS
implementation for future virtio-net hardware
- Performance benefit of software RSS (as well as implementation in EBPF)
is delivery of each packet to proper virtqueue/CPU and avoiding packet
rescheduling in the guest
- The best thing (IMO) would be to implement hash delivery with vhost=on,
i.e. in EBPF and as soon as this is possible - rely on the hardware/host
capabilities and stop calculating the hash in the guest driver (as we do
today in Windows)




> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  hw/net/virtio-net.c | 21 +++++++++++----------
>  1 file changed, 11 insertions(+), 10 deletions(-)
>
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 7bb91617d0..1fa020d905 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -1260,10 +1260,12 @@ static bool virtio_net_attach_epbf_rss(VirtIONet
> *n)
>
>      if (!ebpf_rss_set_all(&n->ebpf_rss, &config,
>                            n->rss_data.indirections_table,
> n->rss_data.key)) {
> +        warn_report("Failed to configure eBPF RSS");
>          return false;
>      }
>
>      if (!virtio_net_attach_ebpf_to_backend(n->nic,
> n->ebpf_rss.program_fd)) {
> +        warn_report("Failed to attach eBPF to backend");
>          return false;
>      }
>
> @@ -1278,16 +1280,10 @@ static void virtio_net_detach_epbf_rss(VirtIONet
> *n)
>  static void virtio_net_commit_rss_config(VirtIONet *n)
>  {
>      if (n->rss_data.enabled) {
> -        n->rss_data.enabled_software_rss = n->rss_data.populate_hash;
> +        n->rss_data.enabled_software_rss = n->rss_data.populate_hash ||
> +                                           !virtio_net_attach_epbf_rss(n);
>          if (n->rss_data.populate_hash) {
>              virtio_net_detach_epbf_rss(n);
> -        } else if (!virtio_net_attach_epbf_rss(n)) {
> -            if (get_vhost_net(qemu_get_queue(n->nic)->peer)) {
> -                warn_report("Can't load eBPF RSS for vhost");
> -            } else {
> -                warn_report("Can't load eBPF RSS - fallback to software
> RSS");
> -                n->rss_data.enabled_software_rss = true;
> -            }
>          }
>
>          trace_virtio_net_rss_enable(n->rss_data.hash_types,
> @@ -3747,8 +3743,13 @@ static void virtio_net_device_realize(DeviceState
> *dev, Error **errp)
>
>      if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS) &&
>          !virtio_net_load_ebpf(n)) {
> -        error_setg(errp, "Can't load eBPF RSS");
> -        virtio_net_device_unrealize(dev);
> +        if (get_vhost_net(nc->peer)) {
> +            error_setg(errp, "Can't load eBPF RSS for vhost");
> +            virtio_net_device_unrealize(dev);
> +            return;
> +        }
> +
> +        warn_report_once("Can't load eBPF RSS - fallback to software
> RSS");
>      }
>  }
>
> --
> 2.42.0
>
>

[-- Attachment #2: Type: text/html, Size: 4778 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-10-30 12:21     ` Akihiko Odaki
@ 2023-10-30 12:51       ` Yuri Benditovich
  2023-10-30 13:14         ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Yuri Benditovich @ 2023-10-30 12:51 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: qemu-devel, Andrew Melnychenko, Michael S . Tsirkin, Jason Wang

[-- Attachment #1: Type: text/plain, Size: 1468 bytes --]

On Mon, Oct 30, 2023 at 2:21 PM Akihiko Odaki <akihiko.odaki@daynix.com>
wrote:

> On 2023/10/30 21:14, Yuri Benditovich wrote:
> >
> >
> > On Mon, Oct 30, 2023 at 7:14 AM Akihiko Odaki <akihiko.odaki@daynix.com
> > <mailto:akihiko.odaki@daynix.com>> wrote:
> >
> >     vhost requires eBPF for RSS. When eBPF is not available, virtio-net
> >     implicitly disables RSS even if the user explicitly requests it.
> Return
> >     an error instead of implicitly disabling RSS if RSS is requested but
> not
> >     available.
> >
> >
> > I think that suggesting RSS feature when in fact it is not available is
> > not a good idea, this rather desinforms the guest.
> > Existing behavior (IMHO) makes more sense.
> > We can extend this discussion if needed, of course.
>
> This change is not to advertise RSS when it's not available; it instead
> reports an error to the user.
>
> For example, think of the following command line:
> qemu-system-x86_64 -device virtio-net,rss=on,netdev=n -netdev user,id=n
>
> Before this change, it gives no error and the user will not know RSS is
> not available. With this change it now gives an error as follows:
> qemu-system-x86_64: -device virtio-net,rss=on,netdev=n: Can't load eBPF RSS
>

Does this mean failure to run QEMU if the RSS required in the command line
and EBPF can't be loaded?
(for example if we run the system with kernel < 5.8)?
I'm not sure this is user-friendly behavior...

[-- Attachment #2: Type: text/html, Size: 2080 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-10-30 12:51       ` Yuri Benditovich
@ 2023-10-30 13:14         ` Akihiko Odaki
  2023-11-01  4:19           ` Jason Wang
  0 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-30 13:14 UTC (permalink / raw)
  To: Yuri Benditovich, Jason Wang
  Cc: qemu-devel, Andrew Melnychenko, Michael S . Tsirkin

On 2023/10/30 21:51, Yuri Benditovich wrote:
> 
> 
> On Mon, Oct 30, 2023 at 2:21 PM Akihiko Odaki <akihiko.odaki@daynix.com 
> <mailto:akihiko.odaki@daynix.com>> wrote:
> 
>     On 2023/10/30 21:14, Yuri Benditovich wrote:
>      >
>      >
>      > On Mon, Oct 30, 2023 at 7:14 AM Akihiko Odaki
>     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
>      > <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>> wrote:
>      >
>      >     vhost requires eBPF for RSS. When eBPF is not available,
>     virtio-net
>      >     implicitly disables RSS even if the user explicitly requests
>     it. Return
>      >     an error instead of implicitly disabling RSS if RSS is
>     requested but not
>      >     available.
>      >
>      >
>      > I think that suggesting RSS feature when in fact it is not
>     available is
>      > not a good idea, this rather desinforms the guest.
>      > Existing behavior (IMHO) makes more sense.
>      > We can extend this discussion if needed, of course.
> 
>     This change is not to advertise RSS when it's not available; it instead
>     reports an error to the user.
> 
>     For example, think of the following command line:
>     qemu-system-x86_64 -device virtio-net,rss=on,netdev=n -netdev user,id=n
> 
>     Before this change, it gives no error and the user will not know RSS is
>     not available. With this change it now gives an error as follows:
>     qemu-system-x86_64: -device virtio-net,rss=on,netdev=n: Can't load
>     eBPF RSS
> 
> 
> Does this mean failure to run QEMU if the RSS required in the command 
> line and EBPF can't be loaded?
> (for example if we run the system with kernel < 5.8)?
> I'm not sure this is user-friendly behavior...

This patch is wrong that it assumes software RSS is not enabled at all; 
I missed the vhost check before clearing VIRTIO_NET_F_RSS in 
virtio_net_get_features().

That said, I indeed intend to make it return a hard error for the case 
that RSS is requested for vhost but eBPF can't be loaded.

I believe the current behavior of implicitly disabling a feature 
explicitly requested by the user is not good, but we can still emit a 
warning instead of an error.

It's better to follow a convention common in QEMU but I see no 
documentation regarding this kind of situation. I know virtio-gpu gives 
an error in such a case but it's just one example.

I'd also like to ask Jason if we should have a warning or error. Perhaps 
we may better consult QOM maintainers too.


^ permalink raw reply	[flat|nested] 59+ messages in thread

* RE: [PATCH v6 05/21] tap: Remove tap_receive()
  2023-10-30  5:12 ` [PATCH v6 05/21] tap: Remove tap_receive() Akihiko Odaki
@ 2023-10-30 18:52   ` Zhang, Chen
  2023-10-31  4:57     ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Zhang, Chen @ 2023-10-30 18:52 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang



> -----Original Message-----
> From: qemu-devel-bounces+chen.zhang=intel.com@nongnu.org <qemu-
> devel-bounces+chen.zhang=intel.com@nongnu.org> On Behalf Of Akihiko
> Odaki
> Sent: Monday, October 30, 2023 1:12 PM
> Cc: qemu-devel@nongnu.org; Yuri Benditovich
> <yuri.benditovich@daynix.com>; Andrew Melnychenko
> <andrew@daynix.com>; Michael S . Tsirkin <mst@redhat.com>; Jason Wang
> <jasowang@redhat.com>; Akihiko Odaki <akihiko.odaki@daynix.com>
> Subject: [PATCH v6 05/21] tap: Remove tap_receive()
> 
> The receive member of NetClientInfo is only for legacy clients and the
> receive_iov member is always used when it is set.

Under normal circumstances we still need to maintain compatibility.
It seems that there is no need to remove the tap_receive here.
You just need to optimize the tap_receive to call the tap_receive_iov.
In the history, we can see a large number of devices still keep this interface,
For example, e1000_receive can directly call the e1000_receive_iov.

Thanks
Chen


> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  net/tap.c | 36 ------------------------------------
>  1 file changed, 36 deletions(-)
> 
> diff --git a/net/tap.c b/net/tap.c
> index d54e90f184..ab4e5a0e91 100644
> --- a/net/tap.c
> +++ b/net/tap.c
> @@ -133,41 +133,6 @@ static ssize_t tap_receive_iov(NetClientState *nc,
> const struct iovec *iov,
>      return tap_write_packet(s, iovp, iovcnt);  }
> 
> -static ssize_t tap_receive_raw(NetClientState *nc, const uint8_t *buf, size_t
> size) -{
> -    TAPState *s = DO_UPCAST(TAPState, nc, nc);
> -    struct iovec iov[2];
> -    int iovcnt = 0;
> -    struct virtio_net_hdr_mrg_rxbuf hdr = { };
> -
> -    if (s->host_vnet_hdr_len) {
> -        iov[iovcnt].iov_base = &hdr;
> -        iov[iovcnt].iov_len  = s->host_vnet_hdr_len;
> -        iovcnt++;
> -    }
> -
> -    iov[iovcnt].iov_base = (char *)buf;
> -    iov[iovcnt].iov_len  = size;
> -    iovcnt++;
> -
> -    return tap_write_packet(s, iov, iovcnt);
> -}
> -
> -static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size) -{
> -    TAPState *s = DO_UPCAST(TAPState, nc, nc);
> -    struct iovec iov[1];
> -
> -    if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
> -        return tap_receive_raw(nc, buf, size);
> -    }
> -
> -    iov[0].iov_base = (char *)buf;
> -    iov[0].iov_len  = size;
> -
> -    return tap_write_packet(s, iov, 1);
> -}
> -
>  #ifndef __sun__
>  ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)  { @@ -366,7
> +331,6 @@ int tap_get_fd(NetClientState *nc)  static NetClientInfo
> net_tap_info = {
>      .type = NET_CLIENT_DRIVER_TAP,
>      .size = sizeof(TAPState),
> -    .receive = tap_receive,
>      .receive_iov = tap_receive_iov,
>      .poll = tap_poll,
>      .cleanup = tap_cleanup,
> --
> 2.42.0
> 



^ permalink raw reply	[flat|nested] 59+ messages in thread

* RE: [PATCH v6 13/21] virtio-net: Always set populate_hash
  2023-10-30  5:12 ` [PATCH v6 13/21] virtio-net: Always set populate_hash Akihiko Odaki
@ 2023-10-30 19:02   ` Zhang, Chen
  2023-10-31  4:47     ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Zhang, Chen @ 2023-10-30 19:02 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang



> -----Original Message-----
> From: qemu-devel-bounces+chen.zhang=intel.com@nongnu.org <qemu-
> devel-bounces+chen.zhang=intel.com@nongnu.org> On Behalf Of Akihiko
> Odaki
> Sent: Monday, October 30, 2023 1:13 PM
> Cc: qemu-devel@nongnu.org; Yuri Benditovich
> <yuri.benditovich@daynix.com>; Andrew Melnychenko
> <andrew@daynix.com>; Michael S . Tsirkin <mst@redhat.com>; Jason Wang
> <jasowang@redhat.com>; Akihiko Odaki <akihiko.odaki@daynix.com>
> Subject: [PATCH v6 13/21] virtio-net: Always set populate_hash
> 
> The member is not cleared during reset so may have a stale value.
> 

/docs/devel/ebpf_rss.rst:
populate_hash - for now, not used. eBPF RSS doesn't support hash reporting.

We need update docs?
And why not clear it in virtio_net_reset function?

Thanks
Chen

> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  hw/net/virtio-net.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index
> 1fa020d905..0fe75b3c08 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -650,6 +650,7 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n,
> int mergeable_rx_bufs,
>          n->guest_hdr_len = n->mergeable_rx_bufs ?
>              sizeof(struct virtio_net_hdr_mrg_rxbuf) :
>              sizeof(struct virtio_net_hdr);
> +        n->rss_data.populate_hash = false;
>      }
> 
>      for (i = 0; i < n->max_queue_pairs; i++) {
> --
> 2.42.0
> 



^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 13/21] virtio-net: Always set populate_hash
  2023-10-30 19:02   ` Zhang, Chen
@ 2023-10-31  4:47     ` Akihiko Odaki
  0 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-31  4:47 UTC (permalink / raw)
  To: Zhang, Chen
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang

On 2023/10/31 4:02, Zhang, Chen wrote:
> 
> 
>> -----Original Message-----
>> From: qemu-devel-bounces+chen.zhang=intel.com@nongnu.org <qemu-
>> devel-bounces+chen.zhang=intel.com@nongnu.org> On Behalf Of Akihiko
>> Odaki
>> Sent: Monday, October 30, 2023 1:13 PM
>> Cc: qemu-devel@nongnu.org; Yuri Benditovich
>> <yuri.benditovich@daynix.com>; Andrew Melnychenko
>> <andrew@daynix.com>; Michael S . Tsirkin <mst@redhat.com>; Jason Wang
>> <jasowang@redhat.com>; Akihiko Odaki <akihiko.odaki@daynix.com>
>> Subject: [PATCH v6 13/21] virtio-net: Always set populate_hash
>>
>> The member is not cleared during reset so may have a stale value.
>>
> 
> /docs/devel/ebpf_rss.rst:
> populate_hash - for now, not used. eBPF RSS doesn't support hash reporting.
> 
> We need update docs?
> And why not clear it in virtio_net_reset function?

Certainly the documentation needs to be updated.
Either of clearing it in virtio_net_reset() or 
virtio_net_set_mrg_rx_bufs() is fine.

Regards,
Akihiko Odaki


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 05/21] tap: Remove tap_receive()
  2023-10-30 18:52   ` Zhang, Chen
@ 2023-10-31  4:57     ` Akihiko Odaki
  0 siblings, 0 replies; 59+ messages in thread
From: Akihiko Odaki @ 2023-10-31  4:57 UTC (permalink / raw)
  To: Zhang, Chen
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang

On 2023/10/31 3:52, Zhang, Chen wrote:
> 
> 
>> -----Original Message-----
>> From: qemu-devel-bounces+chen.zhang=intel.com@nongnu.org <qemu-
>> devel-bounces+chen.zhang=intel.com@nongnu.org> On Behalf Of Akihiko
>> Odaki
>> Sent: Monday, October 30, 2023 1:12 PM
>> Cc: qemu-devel@nongnu.org; Yuri Benditovich
>> <yuri.benditovich@daynix.com>; Andrew Melnychenko
>> <andrew@daynix.com>; Michael S . Tsirkin <mst@redhat.com>; Jason Wang
>> <jasowang@redhat.com>; Akihiko Odaki <akihiko.odaki@daynix.com>
>> Subject: [PATCH v6 05/21] tap: Remove tap_receive()
>>
>> The receive member of NetClientInfo is only for legacy clients and the
>> receive_iov member is always used when it is set.
> 
> Under normal circumstances we still need to maintain compatibility.
> It seems that there is no need to remove the tap_receive here.
> You just need to optimize the tap_receive to call the tap_receive_iov.
> In the history, we can see a large number of devices still keep this interface,
> For example, e1000_receive can directly call the e1000_receive_iov.

That sounds a good idea. I'll do so in the next version.

Regards,
Akihiko Odaki


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-10-30 13:14         ` Akihiko Odaki
@ 2023-11-01  4:19           ` Jason Wang
  2023-11-01  4:50             ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Jason Wang @ 2023-11-01  4:19 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Yuri Benditovich, qemu-devel, Andrew Melnychenko, Michael S . Tsirkin

On Mon, Oct 30, 2023 at 9:15 PM Akihiko Odaki <akihiko.odaki@daynix.com> wrote:
>
> On 2023/10/30 21:51, Yuri Benditovich wrote:
> >
> >
> > On Mon, Oct 30, 2023 at 2:21 PM Akihiko Odaki <akihiko.odaki@daynix.com
> > <mailto:akihiko.odaki@daynix.com>> wrote:
> >
> >     On 2023/10/30 21:14, Yuri Benditovich wrote:
> >      >
> >      >
> >      > On Mon, Oct 30, 2023 at 7:14 AM Akihiko Odaki
> >     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
> >      > <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>> wrote:
> >      >
> >      >     vhost requires eBPF for RSS. When eBPF is not available,
> >     virtio-net
> >      >     implicitly disables RSS even if the user explicitly requests
> >     it. Return
> >      >     an error instead of implicitly disabling RSS if RSS is
> >     requested but not
> >      >     available.
> >      >
> >      >
> >      > I think that suggesting RSS feature when in fact it is not
> >     available is
> >      > not a good idea, this rather desinforms the guest.
> >      > Existing behavior (IMHO) makes more sense.
> >      > We can extend this discussion if needed, of course.
> >
> >     This change is not to advertise RSS when it's not available; it instead
> >     reports an error to the user.
> >
> >     For example, think of the following command line:
> >     qemu-system-x86_64 -device virtio-net,rss=on,netdev=n -netdev user,id=n
> >
> >     Before this change, it gives no error and the user will not know RSS is
> >     not available. With this change it now gives an error as follows:
> >     qemu-system-x86_64: -device virtio-net,rss=on,netdev=n: Can't load
> >     eBPF RSS
> >
> >
> > Does this mean failure to run QEMU if the RSS required in the command
> > line and EBPF can't be loaded?
> > (for example if we run the system with kernel < 5.8)?
> > I'm not sure this is user-friendly behavior...
>
> This patch is wrong that it assumes software RSS is not enabled at all;
> I missed the vhost check before clearing VIRTIO_NET_F_RSS in
> virtio_net_get_features().
>
> That said, I indeed intend to make it return a hard error for the case
> that RSS is requested for vhost but eBPF can't be loaded.
>
> I believe the current behavior of implicitly disabling a feature
> explicitly requested by the user is not good,

Yes, but it has been there for years. It complicates a lot to stick to
the migration compatibility.

> but we can still emit a warning instead of an error.
>
> It's better to follow a convention common in QEMU but I see no
> documentation regarding this kind of situation. I know virtio-gpu gives
> an error in such a case but it's just one example.

The problem is that it's too late to fix old Qemu, so we probably
can't do more than using compatibility flags...

>
> I'd also like to ask Jason if we should have a warning or error. Perhaps
> we may better consult QOM maintainers too.
>

Thanks



^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-01  4:19           ` Jason Wang
@ 2023-11-01  4:50             ` Akihiko Odaki
  2023-11-01  6:38               ` Michael S. Tsirkin
  0 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-11-01  4:50 UTC (permalink / raw)
  To: Jason Wang
  Cc: Yuri Benditovich, qemu-devel, Andrew Melnychenko, Michael S . Tsirkin

On 2023/11/01 13:19, Jason Wang wrote:
> On Mon, Oct 30, 2023 at 9:15 PM Akihiko Odaki <akihiko.odaki@daynix.com> wrote:
>>
>> On 2023/10/30 21:51, Yuri Benditovich wrote:
>>>
>>>
>>> On Mon, Oct 30, 2023 at 2:21 PM Akihiko Odaki <akihiko.odaki@daynix.com
>>> <mailto:akihiko.odaki@daynix.com>> wrote:
>>>
>>>      On 2023/10/30 21:14, Yuri Benditovich wrote:
>>>       >
>>>       >
>>>       > On Mon, Oct 30, 2023 at 7:14 AM Akihiko Odaki
>>>      <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
>>>       > <mailto:akihiko.odaki@daynix.com
>>>      <mailto:akihiko.odaki@daynix.com>>> wrote:
>>>       >
>>>       >     vhost requires eBPF for RSS. When eBPF is not available,
>>>      virtio-net
>>>       >     implicitly disables RSS even if the user explicitly requests
>>>      it. Return
>>>       >     an error instead of implicitly disabling RSS if RSS is
>>>      requested but not
>>>       >     available.
>>>       >
>>>       >
>>>       > I think that suggesting RSS feature when in fact it is not
>>>      available is
>>>       > not a good idea, this rather desinforms the guest.
>>>       > Existing behavior (IMHO) makes more sense.
>>>       > We can extend this discussion if needed, of course.
>>>
>>>      This change is not to advertise RSS when it's not available; it instead
>>>      reports an error to the user.
>>>
>>>      For example, think of the following command line:
>>>      qemu-system-x86_64 -device virtio-net,rss=on,netdev=n -netdev user,id=n
>>>
>>>      Before this change, it gives no error and the user will not know RSS is
>>>      not available. With this change it now gives an error as follows:
>>>      qemu-system-x86_64: -device virtio-net,rss=on,netdev=n: Can't load
>>>      eBPF RSS
>>>
>>>
>>> Does this mean failure to run QEMU if the RSS required in the command
>>> line and EBPF can't be loaded?
>>> (for example if we run the system with kernel < 5.8)?
>>> I'm not sure this is user-friendly behavior...
>>
>> This patch is wrong that it assumes software RSS is not enabled at all;
>> I missed the vhost check before clearing VIRTIO_NET_F_RSS in
>> virtio_net_get_features().
>>
>> That said, I indeed intend to make it return a hard error for the case
>> that RSS is requested for vhost but eBPF can't be loaded.
>>
>> I believe the current behavior of implicitly disabling a feature
>> explicitly requested by the user is not good,
> 
> Yes, but it has been there for years. It complicates a lot to stick to
> the migration compatibility.
> 
>> but we can still emit a warning instead of an error.
>>
>> It's better to follow a convention common in QEMU but I see no
>> documentation regarding this kind of situation. I know virtio-gpu gives
>> an error in such a case but it's just one example.
> 
> The problem is that it's too late to fix old Qemu, so we probably
> can't do more than using compatibility flags...

This patch does not affect migration in my understanding; it does not 
touch any VM state or runtime behavior.

We had another discussion regarding migration for patch "virtio-net: Do 
not clear VIRTIO_NET_F_HASH_REPORT". It does change the runtime behavior 
so we need to take migration into account. I still think the patch does 
not require a compatibility flag since it only exposes a new feature and 
does not prevent migrating from old QEMU that exposes less features. It 
instead fixes the case where migrating between hosts with different tap 
feature sets.

Regards,
Akihiko Odaki


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-01  4:50             ` Akihiko Odaki
@ 2023-11-01  6:38               ` Michael S. Tsirkin
  2023-11-01  8:35                 ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Michael S. Tsirkin @ 2023-11-01  6:38 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Jason Wang, Yuri Benditovich, qemu-devel, Andrew Melnychenko

On Wed, Nov 01, 2023 at 01:50:00PM +0900, Akihiko Odaki wrote:
> We had another discussion regarding migration for patch "virtio-net: Do not
> clear VIRTIO_NET_F_HASH_REPORT". It does change the runtime behavior so we
> need to take migration into account. I still think the patch does not
> require a compatibility flag since it only exposes a new feature and does
> not prevent migrating from old QEMU that exposes less features. It instead
> fixes the case where migrating between hosts with different tap feature
> sets.

When in doubt, add a compat flag.

-- 
MST



^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-01  6:38               ` Michael S. Tsirkin
@ 2023-11-01  8:35                 ` Akihiko Odaki
  2023-11-01  9:09                   ` Michael S. Tsirkin
  0 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-11-01  8:35 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Jason Wang, Yuri Benditovich, qemu-devel, Andrew Melnychenko

On 2023/11/01 15:38, Michael S. Tsirkin wrote:
> On Wed, Nov 01, 2023 at 01:50:00PM +0900, Akihiko Odaki wrote:
>> We had another discussion regarding migration for patch "virtio-net: Do not
>> clear VIRTIO_NET_F_HASH_REPORT". It does change the runtime behavior so we
>> need to take migration into account. I still think the patch does not
>> require a compatibility flag since it only exposes a new feature and does
>> not prevent migrating from old QEMU that exposes less features. It instead
>> fixes the case where migrating between hosts with different tap feature
>> sets.
> 
> When in doubt, add a compat flag.

Personally I'm confident about the migration compatibility with patch 
"virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT". virtio-net already 
does the same thing when the tap implementation on the destination 
implements virtio-net header support while the counterpart of the source 
does not.


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-01  8:35                 ` Akihiko Odaki
@ 2023-11-01  9:09                   ` Michael S. Tsirkin
  2023-11-01  9:15                     ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Michael S. Tsirkin @ 2023-11-01  9:09 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Jason Wang, Yuri Benditovich, qemu-devel, Andrew Melnychenko

On Wed, Nov 01, 2023 at 05:35:50PM +0900, Akihiko Odaki wrote:
> On 2023/11/01 15:38, Michael S. Tsirkin wrote:
> > On Wed, Nov 01, 2023 at 01:50:00PM +0900, Akihiko Odaki wrote:
> > > We had another discussion regarding migration for patch "virtio-net: Do not
> > > clear VIRTIO_NET_F_HASH_REPORT". It does change the runtime behavior so we
> > > need to take migration into account. I still think the patch does not
> > > require a compatibility flag since it only exposes a new feature and does
> > > not prevent migrating from old QEMU that exposes less features. It instead
> > > fixes the case where migrating between hosts with different tap feature
> > > sets.
> > 
> > When in doubt, add a compat flag.
> 
> Personally I'm confident about the migration compatibility with patch
> "virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT". virtio-net already does
> the same thing when the tap implementation on the destination implements
> virtio-net header support while the counterpart of the source does not.

Trust me there's been so many times where we were very sure and
problems come up later. Just don't enable new functionality for
old machine types, problem solved. Why is this hard?

-- 
MST



^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-01  9:09                   ` Michael S. Tsirkin
@ 2023-11-01  9:15                     ` Akihiko Odaki
  2023-11-02  9:09                       ` Yuri Benditovich
  0 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-11-01  9:15 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Jason Wang, Yuri Benditovich, qemu-devel, Andrew Melnychenko

On 2023/11/01 18:09, Michael S. Tsirkin wrote:
> On Wed, Nov 01, 2023 at 05:35:50PM +0900, Akihiko Odaki wrote:
>> On 2023/11/01 15:38, Michael S. Tsirkin wrote:
>>> On Wed, Nov 01, 2023 at 01:50:00PM +0900, Akihiko Odaki wrote:
>>>> We had another discussion regarding migration for patch "virtio-net: Do not
>>>> clear VIRTIO_NET_F_HASH_REPORT". It does change the runtime behavior so we
>>>> need to take migration into account. I still think the patch does not
>>>> require a compatibility flag since it only exposes a new feature and does
>>>> not prevent migrating from old QEMU that exposes less features. It instead
>>>> fixes the case where migrating between hosts with different tap feature
>>>> sets.
>>>
>>> When in doubt, add a compat flag.
>>
>> Personally I'm confident about the migration compatibility with patch
>> "virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT". virtio-net already does
>> the same thing when the tap implementation on the destination implements
>> virtio-net header support while the counterpart of the source does not.
> 
> Trust me there's been so many times where we were very sure and
> problems come up later. Just don't enable new functionality for
> old machine types, problem solved. Why is this hard?

I see. I'll add a compatibility flag for VIRTIO_NET_F_HASH_REPORT 
exposure; it should be quite easy.


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-01  9:15                     ` Akihiko Odaki
@ 2023-11-02  9:09                       ` Yuri Benditovich
  2023-11-02  9:33                         ` Michael S. Tsirkin
  0 siblings, 1 reply; 59+ messages in thread
From: Yuri Benditovich @ 2023-11-02  9:09 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Michael S. Tsirkin, Jason Wang, qemu-devel, Andrew Melnychenko

[-- Attachment #1: Type: text/plain, Size: 1784 bytes --]

Probably we mix two different patches in this discussion.
Focusing on the patch in the e-mail header:

IMO it is not acceptable to fail QEMU run for one feature that we can't
make active when we silently drop all other features in such a case.

On Wed, Nov 1, 2023 at 11:15 AM Akihiko Odaki <akihiko.odaki@daynix.com>
wrote:

> On 2023/11/01 18:09, Michael S. Tsirkin wrote:
> > On Wed, Nov 01, 2023 at 05:35:50PM +0900, Akihiko Odaki wrote:
> >> On 2023/11/01 15:38, Michael S. Tsirkin wrote:
> >>> On Wed, Nov 01, 2023 at 01:50:00PM +0900, Akihiko Odaki wrote:
> >>>> We had another discussion regarding migration for patch "virtio-net:
> Do not
> >>>> clear VIRTIO_NET_F_HASH_REPORT". It does change the runtime behavior
> so we
> >>>> need to take migration into account. I still think the patch does not
> >>>> require a compatibility flag since it only exposes a new feature and
> does
> >>>> not prevent migrating from old QEMU that exposes less features. It
> instead
> >>>> fixes the case where migrating between hosts with different tap
> feature
> >>>> sets.
> >>>
> >>> When in doubt, add a compat flag.
> >>
> >> Personally I'm confident about the migration compatibility with patch
> >> "virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT". virtio-net already
> does
> >> the same thing when the tap implementation on the destination implements
> >> virtio-net header support while the counterpart of the source does not.
> >
> > Trust me there's been so many times where we were very sure and
> > problems come up later. Just don't enable new functionality for
> > old machine types, problem solved. Why is this hard?
>
> I see. I'll add a compatibility flag for VIRTIO_NET_F_HASH_REPORT
> exposure; it should be quite easy.
>

[-- Attachment #2: Type: text/html, Size: 2338 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-02  9:09                       ` Yuri Benditovich
@ 2023-11-02  9:33                         ` Michael S. Tsirkin
  2023-11-02 10:20                           ` Yuri Benditovich
  0 siblings, 1 reply; 59+ messages in thread
From: Michael S. Tsirkin @ 2023-11-02  9:33 UTC (permalink / raw)
  To: Yuri Benditovich
  Cc: Akihiko Odaki, Jason Wang, qemu-devel, Andrew Melnychenko

On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri Benditovich wrote:
> Probably we mix two different patches in this discussion.
> Focusing on the patch in the e-mail header:
> 
> IMO it is not acceptable to fail QEMU run for one feature that we can't make
> active when we silently drop all other features in such a case.

If the feature is off by default then it seems more reasonable
and silent masking can be seen as a bug.
Most virtio features are on by default this is why it's
reasonable to mask them.

-- 
MST



^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-02  9:33                         ` Michael S. Tsirkin
@ 2023-11-02 10:20                           ` Yuri Benditovich
  2023-11-02 11:26                             ` Michael S. Tsirkin
  2023-11-02 14:56                             ` Akihiko Odaki
  0 siblings, 2 replies; 59+ messages in thread
From: Yuri Benditovich @ 2023-11-02 10:20 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Akihiko Odaki, Jason Wang, qemu-devel, Andrew Melnychenko

[-- Attachment #1: Type: text/plain, Size: 885 bytes --]

On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin <mst@redhat.com> wrote:

> On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri Benditovich wrote:
> > Probably we mix two different patches in this discussion.
> > Focusing on the patch in the e-mail header:
> >
> > IMO it is not acceptable to fail QEMU run for one feature that we can't
> make
> > active when we silently drop all other features in such a case.
>
> If the feature is off by default then it seems more reasonable
> and silent masking can be seen as a bug.
> Most virtio features are on by default this is why it's
> reasonable to mask them.
>
>
If we are talking about RSS: setting it initially off is the development
time decision.
When it will be completely stable there is no reason to keep it off by
default, so this is more a question of time and of a readiness of libvirt.

> --
> MST
>
>

[-- Attachment #2: Type: text/html, Size: 1400 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-02 10:20                           ` Yuri Benditovich
@ 2023-11-02 11:26                             ` Michael S. Tsirkin
  2023-11-02 12:00                               ` Yuri Benditovich
  2023-11-02 14:56                             ` Akihiko Odaki
  1 sibling, 1 reply; 59+ messages in thread
From: Michael S. Tsirkin @ 2023-11-02 11:26 UTC (permalink / raw)
  To: Yuri Benditovich
  Cc: Akihiko Odaki, Jason Wang, qemu-devel, Andrew Melnychenko

On Thu, Nov 02, 2023 at 12:20:39PM +0200, Yuri Benditovich wrote:
> 
> 
> On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin <mst@redhat.com> wrote:
> 
>     On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri Benditovich wrote:
>     > Probably we mix two different patches in this discussion.
>     > Focusing on the patch in the e-mail header:
>     >
>     > IMO it is not acceptable to fail QEMU run for one feature that we can't
>     make
>     > active when we silently drop all other features in such a case.
> 
>     If the feature is off by default then it seems more reasonable
>     and silent masking can be seen as a bug.
>     Most virtio features are on by default this is why it's
>     reasonable to mask them.
> 
> 
> 
> If we are talking about RSS: setting it initially off is the development time
> decision. 
> When it will be completely stable there is no reason to keep it off by default,
> so this is more a question of time and of a readiness of libvirt. 

Well when we flip the default we'll need compat machinery for sure ;)

-- 
MST



^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-02 11:26                             ` Michael S. Tsirkin
@ 2023-11-02 12:00                               ` Yuri Benditovich
  2023-11-02 13:18                                 ` Michael S. Tsirkin
  0 siblings, 1 reply; 59+ messages in thread
From: Yuri Benditovich @ 2023-11-02 12:00 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Akihiko Odaki, Jason Wang, qemu-devel, Andrew Melnychenko

[-- Attachment #1: Type: text/plain, Size: 1505 bytes --]

On Thu, Nov 2, 2023 at 1:26 PM Michael S. Tsirkin <mst@redhat.com> wrote:

> On Thu, Nov 02, 2023 at 12:20:39PM +0200, Yuri Benditovich wrote:
> >
> >
> > On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin <mst@redhat.com>
> wrote:
> >
> >     On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri Benditovich wrote:
> >     > Probably we mix two different patches in this discussion.
> >     > Focusing on the patch in the e-mail header:
> >     >
> >     > IMO it is not acceptable to fail QEMU run for one feature that we
> can't
> >     make
> >     > active when we silently drop all other features in such a case.
> >
> >     If the feature is off by default then it seems more reasonable
> >     and silent masking can be seen as a bug.
> >     Most virtio features are on by default this is why it's
> >     reasonable to mask them.
> >
> >
> >
> > If we are talking about RSS: setting it initially off is the development
> time
> > decision.
> > When it will be completely stable there is no reason to keep it off by
> default,
> > so this is more a question of time and of a readiness of libvirt.
>
> Well when we flip the default we'll need compat machinery for sure ;)
>

Of course, on the flip or default we'll need to keep compatibility to
earlier machine types.
But, because in the perspective it makes sense to make the RSS is on by
default, I do not think we need _now_ to make qemu fail to start if the
ebpf can't be loaded.


>
> --
> MST
>
>

[-- Attachment #2: Type: text/html, Size: 2231 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-02 12:00                               ` Yuri Benditovich
@ 2023-11-02 13:18                                 ` Michael S. Tsirkin
  0 siblings, 0 replies; 59+ messages in thread
From: Michael S. Tsirkin @ 2023-11-02 13:18 UTC (permalink / raw)
  To: Yuri Benditovich
  Cc: Akihiko Odaki, Jason Wang, qemu-devel, Andrew Melnychenko

On Thu, Nov 02, 2023 at 02:00:46PM +0200, Yuri Benditovich wrote:
> 
> 
> On Thu, Nov 2, 2023 at 1:26 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> 
>     On Thu, Nov 02, 2023 at 12:20:39PM +0200, Yuri Benditovich wrote:
>     >
>     >
>     > On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin <mst@redhat.com>
>     wrote:
>     >
>     >     On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri Benditovich wrote:
>     >     > Probably we mix two different patches in this discussion.
>     >     > Focusing on the patch in the e-mail header:
>     >     >
>     >     > IMO it is not acceptable to fail QEMU run for one feature that we
>     can't
>     >     make
>     >     > active when we silently drop all other features in such a case.
>     >
>     >     If the feature is off by default then it seems more reasonable
>     >     and silent masking can be seen as a bug.
>     >     Most virtio features are on by default this is why it's
>     >     reasonable to mask them.
>     >
>     >
>     >
>     > If we are talking about RSS: setting it initially off is the development
>     time
>     > decision. 
>     > When it will be completely stable there is no reason to keep it off by
>     default,
>     > so this is more a question of time and of a readiness of libvirt. 
> 
>     Well when we flip the default we'll need compat machinery for sure ;)
> 
> 
> Of course, on the flip or default we'll need to keep compatibility to earlier
> machine types.
> But, because in the perspective it makes sense to make the RSS is on by
> default, I do not think we need _now_ to make qemu fail to start if the ebpf
> can't be loaded.
>  

Generally if user asks for something and we can't do it, we must fail.
If we can't apply a default we need a better default.
qemu has a bug in that it can't generally distinguish between default set
automatically and same default given on command line.

-- 
MST



^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-02 10:20                           ` Yuri Benditovich
  2023-11-02 11:26                             ` Michael S. Tsirkin
@ 2023-11-02 14:56                             ` Akihiko Odaki
  2023-11-03  9:35                               ` Yuri Benditovich
  1 sibling, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-11-02 14:56 UTC (permalink / raw)
  To: Yuri Benditovich, Michael S. Tsirkin
  Cc: Jason Wang, qemu-devel, Andrew Melnychenko

On 2023/11/02 19:20, Yuri Benditovich wrote:
> 
> 
> On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin <mst@redhat.com 
> <mailto:mst@redhat.com>> wrote:
> 
>     On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri Benditovich wrote:
>      > Probably we mix two different patches in this discussion.
>      > Focusing on the patch in the e-mail header:
>      >
>      > IMO it is not acceptable to fail QEMU run for one feature that we
>     can't make
>      > active when we silently drop all other features in such a case.
> 
>     If the feature is off by default then it seems more reasonable
>     and silent masking can be seen as a bug.
>     Most virtio features are on by default this is why it's
>     reasonable to mask them.
> 
> 
> If we are talking about RSS: setting it initially off is the development 
> time decision.
> When it will be completely stable there is no reason to keep it off by 
> default, so this is more a question of time and of a readiness of libvirt.

It is not ok to make "on" the default; that will enable RSS even when 
eBPF steering support is not present and can result in performance 
degradation.

We will need OnOffAuto instead of a simple boolean value if we are going 
to enable RSS when eBPF steering support is available; "auto" will be 
the default and will enable RSS if and only if eBPF steering support is 
available. "on" will not be default so it's better to validate if RSS is 
available when the user explicitly specified "on" for the "rss" property.


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-02 14:56                             ` Akihiko Odaki
@ 2023-11-03  9:35                               ` Yuri Benditovich
  2023-11-03  9:55                                 ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Yuri Benditovich @ 2023-11-03  9:35 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Michael S. Tsirkin, Jason Wang, qemu-devel, Andrew Melnychenko

[-- Attachment #1: Type: text/plain, Size: 1873 bytes --]

On Thu, Nov 2, 2023 at 4:56 PM Akihiko Odaki <akihiko.odaki@daynix.com>
wrote:

> On 2023/11/02 19:20, Yuri Benditovich wrote:
> >
> >
> > On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin <mst@redhat.com
> > <mailto:mst@redhat.com>> wrote:
> >
> >     On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri Benditovich wrote:
> >      > Probably we mix two different patches in this discussion.
> >      > Focusing on the patch in the e-mail header:
> >      >
> >      > IMO it is not acceptable to fail QEMU run for one feature that we
> >     can't make
> >      > active when we silently drop all other features in such a case.
> >
> >     If the feature is off by default then it seems more reasonable
> >     and silent masking can be seen as a bug.
> >     Most virtio features are on by default this is why it's
> >     reasonable to mask them.
> >
> >
> > If we are talking about RSS: setting it initially off is the development
> > time decision.
> > When it will be completely stable there is no reason to keep it off by
> > default, so this is more a question of time and of a readiness of
> libvirt.
>
> It is not ok to make "on" the default; that will enable RSS even when
> eBPF steering support is not present and can result in performance
> degradation.
>

Exactly as it is today - with vhost=on the host does not suggest RSS
without  eBPF.
I do not understand what you call "performance degradation", can you
describe the scenario?


>
> We will need OnOffAuto instead of a simple boolean value if we are going
> to enable RSS when eBPF steering support is available; "auto" will be
> the default and will enable RSS if and only if eBPF steering support is
> available. "on" will not be default so it's better to validate if RSS is
> available when the user explicitly specified "on" for the "rss" property.
>

[-- Attachment #2: Type: text/html, Size: 2735 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-03  9:35                               ` Yuri Benditovich
@ 2023-11-03  9:55                                 ` Akihiko Odaki
  2023-11-03 13:14                                   ` Yuri Benditovich
  0 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-11-03  9:55 UTC (permalink / raw)
  To: Yuri Benditovich
  Cc: Michael S. Tsirkin, Jason Wang, qemu-devel, Andrew Melnychenko

On 2023/11/03 18:35, Yuri Benditovich wrote:
> 
> 
> On Thu, Nov 2, 2023 at 4:56 PM Akihiko Odaki <akihiko.odaki@daynix.com 
> <mailto:akihiko.odaki@daynix.com>> wrote:
> 
>     On 2023/11/02 19:20, Yuri Benditovich wrote:
>      >
>      >
>      > On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin
>     <mst@redhat.com <mailto:mst@redhat.com>
>      > <mailto:mst@redhat.com <mailto:mst@redhat.com>>> wrote:
>      >
>      >     On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri Benditovich wrote:
>      >      > Probably we mix two different patches in this discussion.
>      >      > Focusing on the patch in the e-mail header:
>      >      >
>      >      > IMO it is not acceptable to fail QEMU run for one feature
>     that we
>      >     can't make
>      >      > active when we silently drop all other features in such a
>     case.
>      >
>      >     If the feature is off by default then it seems more reasonable
>      >     and silent masking can be seen as a bug.
>      >     Most virtio features are on by default this is why it's
>      >     reasonable to mask them.
>      >
>      >
>      > If we are talking about RSS: setting it initially off is the
>     development
>      > time decision.
>      > When it will be completely stable there is no reason to keep it
>     off by
>      > default, so this is more a question of time and of a readiness of
>     libvirt.
> 
>     It is not ok to make "on" the default; that will enable RSS even when
>     eBPF steering support is not present and can result in performance
>     degradation.
> 
> 
> Exactly as it is today - with vhost=on the host does not suggest RSS 
> without  eBPF.
> I do not understand what you call "performance degradation", can you 
> describe the scenario?

I was not clear, but I was talking about the case of vhost=off or peers 
other than tap (e.g., user). rss=on employs in-qemu RSS, which incurs 
overheads for such configurations.


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-03  9:55                                 ` Akihiko Odaki
@ 2023-11-03 13:14                                   ` Yuri Benditovich
  2023-11-11 15:28                                     ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Yuri Benditovich @ 2023-11-03 13:14 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Michael S. Tsirkin, Jason Wang, qemu-devel, Andrew Melnychenko

[-- Attachment #1: Type: text/plain, Size: 2613 bytes --]

On Fri, Nov 3, 2023 at 11:55 AM Akihiko Odaki <akihiko.odaki@daynix.com>
wrote:

> On 2023/11/03 18:35, Yuri Benditovich wrote:
> >
> >
> > On Thu, Nov 2, 2023 at 4:56 PM Akihiko Odaki <akihiko.odaki@daynix.com
> > <mailto:akihiko.odaki@daynix.com>> wrote:
> >
> >     On 2023/11/02 19:20, Yuri Benditovich wrote:
> >      >
> >      >
> >      > On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin
> >     <mst@redhat.com <mailto:mst@redhat.com>
> >      > <mailto:mst@redhat.com <mailto:mst@redhat.com>>> wrote:
> >      >
> >      >     On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri Benditovich
> wrote:
> >      >      > Probably we mix two different patches in this discussion.
> >      >      > Focusing on the patch in the e-mail header:
> >      >      >
> >      >      > IMO it is not acceptable to fail QEMU run for one feature
> >     that we
> >      >     can't make
> >      >      > active when we silently drop all other features in such a
> >     case.
> >      >
> >      >     If the feature is off by default then it seems more reasonable
> >      >     and silent masking can be seen as a bug.
> >      >     Most virtio features are on by default this is why it's
> >      >     reasonable to mask them.
> >      >
> >      >
> >      > If we are talking about RSS: setting it initially off is the
> >     development
> >      > time decision.
> >      > When it will be completely stable there is no reason to keep it
> >     off by
> >      > default, so this is more a question of time and of a readiness of
> >     libvirt.
> >
> >     It is not ok to make "on" the default; that will enable RSS even when
> >     eBPF steering support is not present and can result in performance
> >     degradation.
> >
> >
> > Exactly as it is today - with vhost=on the host does not suggest RSS
> > without  eBPF.
> > I do not understand what you call "performance degradation", can you
> > describe the scenario?
>
> I was not clear, but I was talking about the case of vhost=off or peers
> other than tap (e.g., user). rss=on employs in-qemu RSS, which incurs
> overheads for such configurations.
>

So, vhost=off OR peers other than tap:

In the case of peers other than tap (IMO) we're not talking about
performance at all.
Backends like "user" (without vnet_hdr) do not support _many_
performance-oriented features.
If RSS is somehow "supported" for such backends this is rather a
misunderstanding (IMO again).

In the case of tap with vhost=off the RSS support does not create any
performance degradation without eBPF.

[-- Attachment #2: Type: text/html, Size: 3896 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 15/21] virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT
  2023-10-30  5:12 ` [PATCH v6 15/21] virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT Akihiko Odaki
@ 2023-11-03 13:26   ` Yuri Benditovich
  0 siblings, 0 replies; 59+ messages in thread
From: Yuri Benditovich @ 2023-11-03 13:26 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: qemu-devel, Andrew Melnychenko, Michael S . Tsirkin, Jason Wang

[-- Attachment #1: Type: text/plain, Size: 1226 bytes --]

On Mon, Oct 30, 2023 at 7:15 AM Akihiko Odaki <akihiko.odaki@daynix.com>
wrote:

> virtio-net can report hash values even if the peer does not have a
> virtio-net header.
>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  hw/net/virtio-net.c | 2 --
>  1 file changed, 2 deletions(-)
>
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index e30105884c..bdb4579f98 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -774,8 +774,6 @@ static uint64_t virtio_net_get_features(VirtIODevice
> *vdev, uint64_t features,
>          virtio_clear_feature(&features, VIRTIO_NET_F_HOST_USO);
>          virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_USO4);
>          virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_USO6);
> -
> -        virtio_clear_feature(&features, VIRTIO_NET_F_HASH_REPORT);
>      }
>
>
IMO, we should not enable any advanced features for backends without
vnet_hdr unless we have a strong reason to do so.
( HOST_TSO and GUEST_TSO are performance boosters and they are not
supported without vnet_hdr )
I'd rather disable also RSS under this "if".



>      if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
> --
> 2.42.0
>
>

[-- Attachment #2: Type: text/html, Size: 1900 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 06/21] net: Remove flag propagation
  2023-10-30  5:12 ` [PATCH v6 06/21] net: Remove flag propagation Akihiko Odaki
@ 2023-11-10  7:35   ` Pavel Dovgalyuk
  2023-11-11 14:27     ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Pavel Dovgalyuk @ 2023-11-10  7:35 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Pavel Dovgalyuk, Paolo Bonzini,
	Zhang Chen, Li Zhijian

You need to bump REPLAY_VERSION in replay/replay.c, because your patch 
changes the replay log format.

Otherwise, for replay part:
Acked-by: Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>

On 30.10.2023 08:12, Akihiko Odaki wrote:
> There is no defined flag now.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>   include/net/filter.h    |  3 ---
>   include/net/queue.h     |  6 ------
>   include/sysemu/replay.h |  2 +-
>   net/dump.c              |  4 ++--
>   net/filter-buffer.c     |  4 +---
>   net/filter-mirror.c     |  6 ++----
>   net/filter-replay.c     |  3 +--
>   net/filter-rewriter.c   |  5 ++---
>   net/filter.c            |  8 +++-----
>   net/net.c               | 43 ++++++++++++++---------------------------
>   replay/replay-net.c     |  8 ++------
>   11 files changed, 28 insertions(+), 64 deletions(-)
> 
> diff --git a/include/net/filter.h b/include/net/filter.h
> index 27ffc630df..e523771e72 100644
> --- a/include/net/filter.h
> +++ b/include/net/filter.h
> @@ -26,7 +26,6 @@ typedef void (FilterCleanup) (NetFilterState *nf);
>    */
>   typedef ssize_t (FilterReceiveIOV)(NetFilterState *nc,
>                                      NetClientState *sender,
> -                                   unsigned flags,
>                                      const struct iovec *iov,
>                                      int iovcnt,
>                                      NetPacketSent *sent_cb);
> @@ -65,14 +64,12 @@ struct NetFilterState {
>   ssize_t qemu_netfilter_receive(NetFilterState *nf,
>                                  NetFilterDirection direction,
>                                  NetClientState *sender,
> -                               unsigned flags,
>                                  const struct iovec *iov,
>                                  int iovcnt,
>                                  NetPacketSent *sent_cb);
>   
>   /* pass the packet to the next filter */
>   ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
> -                                    unsigned flags,
>                                       const struct iovec *iov,
>                                       int iovcnt,
>                                       void *opaque);
> diff --git a/include/net/queue.h b/include/net/queue.h
> index 7a43863be2..571f4e1436 100644
> --- a/include/net/queue.h
> +++ b/include/net/queue.h
> @@ -30,15 +30,12 @@ typedef struct NetQueue NetQueue;
>   
>   typedef void (NetPacketSent) (NetClientState *sender, ssize_t ret);
>   
> -#define QEMU_NET_PACKET_FLAG_NONE  0
> -
>   /* Returns:
>    *   >0 - success
>    *    0 - queue packet for future redelivery
>    *   <0 - failure (discard packet)
>    */
>   typedef ssize_t (NetQueueDeliverFunc)(NetClientState *sender,
> -                                      unsigned flags,
>                                         const struct iovec *iov,
>                                         int iovcnt,
>                                         void *opaque);
> @@ -47,7 +44,6 @@ NetQueue *qemu_new_net_queue(NetQueueDeliverFunc *deliver, void *opaque);
>   
>   void qemu_net_queue_append_iov(NetQueue *queue,
>                                  NetClientState *sender,
> -                               unsigned flags,
>                                  const struct iovec *iov,
>                                  int iovcnt,
>                                  NetPacketSent *sent_cb);
> @@ -64,14 +60,12 @@ ssize_t qemu_net_queue_receive_iov(NetQueue *queue,
>   
>   ssize_t qemu_net_queue_send(NetQueue *queue,
>                               NetClientState *sender,
> -                            unsigned flags,
>                               const uint8_t *data,
>                               size_t size,
>                               NetPacketSent *sent_cb);
>   
>   ssize_t qemu_net_queue_send_iov(NetQueue *queue,
>                                   NetClientState *sender,
> -                                unsigned flags,
>                                   const struct iovec *iov,
>                                   int iovcnt,
>                                   NetPacketSent *sent_cb);
> diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
> index 08aae5869f..67b2d3ac73 100644
> --- a/include/sysemu/replay.h
> +++ b/include/sysemu/replay.h
> @@ -158,7 +158,7 @@ ReplayNetState *replay_register_net(NetFilterState *nfs);
>   /*! Unregisters replay network filter. */
>   void replay_unregister_net(ReplayNetState *rns);
>   /*! Called to write network packet to the replay log. */
> -void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
> +void replay_net_packet_event(ReplayNetState *rns,
>                                const struct iovec *iov, int iovcnt);
>   
>   /* Audio */
> diff --git a/net/dump.c b/net/dump.c
> index 956e34a123..dd8ada9b5e 100644
> --- a/net/dump.c
> +++ b/net/dump.c
> @@ -150,8 +150,8 @@ struct NetFilterDumpState {
>   };
>   
>   static ssize_t filter_dump_receive_iov(NetFilterState *nf, NetClientState *sndr,
> -                                       unsigned flags, const struct iovec *iov,
> -                                       int iovcnt, NetPacketSent *sent_cb)
> +                                       const struct iovec *iov, int iovcnt,
> +                                       NetPacketSent *sent_cb)
>   {
>       NetFilterDumpState *nfds = FILTER_DUMP(nf);
>   
> diff --git a/net/filter-buffer.c b/net/filter-buffer.c
> index 283dc9cbe6..6d8b581cd8 100644
> --- a/net/filter-buffer.c
> +++ b/net/filter-buffer.c
> @@ -58,7 +58,6 @@ static void filter_buffer_release_timer(void *opaque)
>   /* filter APIs */
>   static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
>                                            NetClientState *sender,
> -                                         unsigned flags,
>                                            const struct iovec *iov,
>                                            int iovcnt,
>                                            NetPacketSent *sent_cb)
> @@ -79,8 +78,7 @@ static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
>        * the packets without caring about the receiver. This is suboptimal.
>        * May need more thoughts (e.g keeping sent_cb).
>        */
> -    qemu_net_queue_append_iov(s->incoming_queue, sender, flags,
> -                              iov, iovcnt, NULL);
> +    qemu_net_queue_append_iov(s->incoming_queue, sender, iov, iovcnt, NULL);
>       return iov_size(iov, iovcnt);
>   }
>   
> diff --git a/net/filter-mirror.c b/net/filter-mirror.c
> index 34a63b5dbb..752571a548 100644
> --- a/net/filter-mirror.c
> +++ b/net/filter-mirror.c
> @@ -145,12 +145,12 @@ static void redirector_to_filter(NetFilterState *nf,
>   
>       if (nf->direction == NET_FILTER_DIRECTION_ALL ||
>           nf->direction == NET_FILTER_DIRECTION_TX) {
> -        qemu_netfilter_pass_to_next(nf->netdev, 0, &iov, 1, nf);
> +        qemu_netfilter_pass_to_next(nf->netdev, &iov, 1, nf);
>       }
>   
>       if (nf->direction == NET_FILTER_DIRECTION_ALL ||
>           nf->direction == NET_FILTER_DIRECTION_RX) {
> -        qemu_netfilter_pass_to_next(nf->netdev->peer, 0, &iov, 1, nf);
> +        qemu_netfilter_pass_to_next(nf->netdev->peer, &iov, 1, nf);
>        }
>   }
>   
> @@ -190,7 +190,6 @@ static void redirector_chr_event(void *opaque, QEMUChrEvent event)
>   
>   static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
>                                            NetClientState *sender,
> -                                         unsigned flags,
>                                            const struct iovec *iov,
>                                            int iovcnt,
>                                            NetPacketSent *sent_cb)
> @@ -212,7 +211,6 @@ static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
>   
>   static ssize_t filter_redirector_receive_iov(NetFilterState *nf,
>                                                NetClientState *sender,
> -                                             unsigned flags,
>                                                const struct iovec *iov,
>                                                int iovcnt,
>                                                NetPacketSent *sent_cb)
> diff --git a/net/filter-replay.c b/net/filter-replay.c
> index 54690676ef..ab132f6f24 100644
> --- a/net/filter-replay.c
> +++ b/net/filter-replay.c
> @@ -31,7 +31,6 @@ struct NetFilterReplayState {
>   
>   static ssize_t filter_replay_receive_iov(NetFilterState *nf,
>                                            NetClientState *sndr,
> -                                         unsigned flags,
>                                            const struct iovec *iov,
>                                            int iovcnt, NetPacketSent *sent_cb)
>   {
> @@ -39,7 +38,7 @@ static ssize_t filter_replay_receive_iov(NetFilterState *nf,
>       switch (replay_mode) {
>       case REPLAY_MODE_RECORD:
>           if (nf->netdev == sndr) {
> -            replay_net_packet_event(nfrs->rns, flags, iov, iovcnt);
> +            replay_net_packet_event(nfrs->rns, iov, iovcnt);
>               return iov_size(iov, iovcnt);
>           }
>           return 0;
> diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
> index c18c4c2019..5da0b097db 100644
> --- a/net/filter-rewriter.c
> +++ b/net/filter-rewriter.c
> @@ -251,7 +251,6 @@ static int handle_secondary_tcp_pkt(RewriterState *rf,
>   
>   static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
>                                            NetClientState *sender,
> -                                         unsigned flags,
>                                            const struct iovec *iov,
>                                            int iovcnt,
>                                            NetPacketSent *sent_cb)
> @@ -294,7 +293,7 @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
>           if (sender == nf->netdev) {
>               /* NET_FILTER_DIRECTION_TX */
>               if (!handle_primary_tcp_pkt(s, conn, pkt, &key)) {
> -                qemu_net_queue_send(s->incoming_queue, sender, 0,
> +                qemu_net_queue_send(s->incoming_queue, sender,
>                   (const uint8_t *)pkt->data, pkt->size, NULL);
>                   packet_destroy(pkt, NULL);
>                   pkt = NULL;
> @@ -307,7 +306,7 @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
>           } else {
>               /* NET_FILTER_DIRECTION_RX */
>               if (!handle_secondary_tcp_pkt(s, conn, pkt, &key)) {
> -                qemu_net_queue_send(s->incoming_queue, sender, 0,
> +                qemu_net_queue_send(s->incoming_queue, sender,
>                   (const uint8_t *)pkt->data, pkt->size, NULL);
>                   packet_destroy(pkt, NULL);
>                   pkt = NULL;
> diff --git a/net/filter.c b/net/filter.c
> index 3335908771..cc870114b7 100644
> --- a/net/filter.c
> +++ b/net/filter.c
> @@ -28,7 +28,6 @@ static inline bool qemu_can_skip_netfilter(NetFilterState *nf)
>   ssize_t qemu_netfilter_receive(NetFilterState *nf,
>                                  NetFilterDirection direction,
>                                  NetClientState *sender,
> -                               unsigned flags,
>                                  const struct iovec *iov,
>                                  int iovcnt,
>                                  NetPacketSent *sent_cb)
> @@ -39,7 +38,7 @@ ssize_t qemu_netfilter_receive(NetFilterState *nf,
>       if (nf->direction == direction ||
>           nf->direction == NET_FILTER_DIRECTION_ALL) {
>           return NETFILTER_GET_CLASS(OBJECT(nf))->receive_iov(
> -                                   nf, sender, flags, iov, iovcnt, sent_cb);
> +                                   nf, sender, iov, iovcnt, sent_cb);
>       }
>   
>       return 0;
> @@ -62,7 +61,6 @@ static NetFilterState *netfilter_next(NetFilterState *nf,
>   }
>   
>   ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
> -                                    unsigned flags,
>                                       const struct iovec *iov,
>                                       int iovcnt,
>                                       void *opaque)
> @@ -96,7 +94,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
>            * to the sender, so sent_cb shouldn't be called later, just
>            * pass NULL to next.
>            */
> -        ret = qemu_netfilter_receive(next, direction, sender, flags, iov,
> +        ret = qemu_netfilter_receive(next, direction, sender, iov,
>                                        iovcnt, NULL);
>           if (ret) {
>               return ret;
> @@ -111,7 +109,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
>        */
>       if (sender && sender->peer) {
>           qemu_net_queue_send_iov(sender->peer->incoming_queue,
> -                                sender, flags, iov, iovcnt, NULL);
> +                                sender, iov, iovcnt, NULL);
>       }
>   
>   out:
> diff --git a/net/net.c b/net/net.c
> index ad8ecce5d6..9883f12940 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -250,7 +250,6 @@ static void qemu_net_client_destructor(NetClientState *nc)
>       g_free(nc);
>   }
>   static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
> -                                       unsigned flags,
>                                          const struct iovec *iov,
>                                          int iovcnt,
>                                          void *opaque);
> @@ -613,7 +612,6 @@ int qemu_can_send_packet(NetClientState *sender)
>   static ssize_t filter_receive_iov(NetClientState *nc,
>                                     NetFilterDirection direction,
>                                     NetClientState *sender,
> -                                  unsigned flags,
>                                     const struct iovec *iov,
>                                     int iovcnt,
>                                     NetPacketSent *sent_cb)
> @@ -623,7 +621,7 @@ static ssize_t filter_receive_iov(NetClientState *nc,
>   
>       if (direction == NET_FILTER_DIRECTION_TX) {
>           QTAILQ_FOREACH(nf, &nc->filters, next) {
> -            ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
> +            ret = qemu_netfilter_receive(nf, direction, sender, iov,
>                                            iovcnt, sent_cb);
>               if (ret) {
>                   return ret;
> @@ -631,7 +629,7 @@ static ssize_t filter_receive_iov(NetClientState *nc,
>           }
>       } else {
>           QTAILQ_FOREACH_REVERSE(nf, &nc->filters, next) {
> -            ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
> +            ret = qemu_netfilter_receive(nf, direction, sender, iov,
>                                            iovcnt, sent_cb);
>               if (ret) {
>                   return ret;
> @@ -645,7 +643,6 @@ static ssize_t filter_receive_iov(NetClientState *nc,
>   static ssize_t filter_receive(NetClientState *nc,
>                                 NetFilterDirection direction,
>                                 NetClientState *sender,
> -                              unsigned flags,
>                                 const uint8_t *data,
>                                 size_t size,
>                                 NetPacketSent *sent_cb)
> @@ -655,7 +652,7 @@ static ssize_t filter_receive(NetClientState *nc,
>           .iov_len = size
>       };
>   
> -    return filter_receive_iov(nc, direction, sender, flags, &iov, 1, sent_cb);
> +    return filter_receive_iov(nc, direction, sender, &iov, 1, sent_cb);
>   }
>   
>   void qemu_purge_queued_packets(NetClientState *nc)
> @@ -692,10 +689,9 @@ void qemu_flush_queued_packets(NetClientState *nc)
>       qemu_flush_or_purge_queued_packets(nc, false);
>   }
>   
> -static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
> -                                                 unsigned flags,
> -                                                 const uint8_t *buf, int size,
> -                                                 NetPacketSent *sent_cb)
> +ssize_t qemu_send_packet_async(NetClientState *sender,
> +                               const uint8_t *buf, int size,
> +                               NetPacketSent *sent_cb)
>   {
>       NetQueue *queue;
>       int ret;
> @@ -711,28 +707,20 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
>   
>       /* Let filters handle the packet first */
>       ret = filter_receive(sender, NET_FILTER_DIRECTION_TX,
> -                         sender, flags, buf, size, sent_cb);
> +                         sender, buf, size, sent_cb);
>       if (ret) {
>           return ret;
>       }
>   
>       ret = filter_receive(sender->peer, NET_FILTER_DIRECTION_RX,
> -                         sender, flags, buf, size, sent_cb);
> +                         sender, buf, size, sent_cb);
>       if (ret) {
>           return ret;
>       }
>   
>       queue = sender->peer->incoming_queue;
>   
> -    return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
> -}
> -
> -ssize_t qemu_send_packet_async(NetClientState *sender,
> -                               const uint8_t *buf, int size,
> -                               NetPacketSent *sent_cb)
> -{
> -    return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE,
> -                                             buf, size, sent_cb);
> +    return qemu_net_queue_send(queue, sender, buf, size, sent_cb);
>   }
>   
>   ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
> @@ -771,7 +759,7 @@ ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
>   }
>   
>   static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
> -                               int iovcnt, unsigned flags)
> +                               int iovcnt)
>   {
>       uint8_t *buf = NULL;
>       uint8_t *buffer;
> @@ -798,7 +786,6 @@ static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
>   }
>   
>   static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
> -                                       unsigned flags,
>                                          const struct iovec *iov,
>                                          int iovcnt,
>                                          void *opaque)
> @@ -827,7 +814,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
>       if (nc->info->receive_iov) {
>           ret = nc->info->receive_iov(nc, iov, iovcnt);
>       } else {
> -        ret = nc_sendv_compat(nc, iov, iovcnt, flags);
> +        ret = nc_sendv_compat(nc, iov, iovcnt);
>       }
>   
>       if (owned_reentrancy_guard) {
> @@ -859,22 +846,20 @@ ssize_t qemu_sendv_packet_async(NetClientState *sender,
>   
>       /* Let filters handle the packet first */
>       ret = filter_receive_iov(sender, NET_FILTER_DIRECTION_TX, sender,
> -                             QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
> +                             iov, iovcnt, sent_cb);
>       if (ret) {
>           return ret;
>       }
>   
>       ret = filter_receive_iov(sender->peer, NET_FILTER_DIRECTION_RX, sender,
> -                             QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
> +                             iov, iovcnt, sent_cb);
>       if (ret) {
>           return ret;
>       }
>   
>       queue = sender->peer->incoming_queue;
>   
> -    return qemu_net_queue_send_iov(queue, sender,
> -                                   QEMU_NET_PACKET_FLAG_NONE,
> -                                   iov, iovcnt, sent_cb);
> +    return qemu_net_queue_send_iov(queue, sender, iov, iovcnt, sent_cb);
>   }
>   
>   ssize_t
> diff --git a/replay/replay-net.c b/replay/replay-net.c
> index 3b70f71cf1..87e6d68f4e 100644
> --- a/replay/replay-net.c
> +++ b/replay/replay-net.c
> @@ -24,7 +24,6 @@ struct ReplayNetState {
>   
>   typedef struct NetEvent {
>       uint8_t id;
> -    uint32_t flags;
>       uint8_t *data;
>       size_t size;
>   } NetEvent;
> @@ -50,11 +49,10 @@ void replay_unregister_net(ReplayNetState *rns)
>       g_free(rns);
>   }
>   
> -void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
> +void replay_net_packet_event(ReplayNetState *rns,
>                                const struct iovec *iov, int iovcnt)
>   {
>       NetEvent *event = g_new(NetEvent, 1);
> -    event->flags = flags;
>       event->data = g_malloc(iov_size(iov, iovcnt));
>       event->size = iov_size(iov, iovcnt);
>       event->id = rns->id;
> @@ -74,7 +72,7 @@ void replay_event_net_run(void *opaque)
>       assert(event->id < network_filters_count);
>   
>       qemu_netfilter_pass_to_next(network_filters[event->id]->netdev,
> -        event->flags, &iov, 1, network_filters[event->id]);
> +        &iov, 1, network_filters[event->id]);
>   
>       g_free(event->data);
>       g_free(event);
> @@ -85,7 +83,6 @@ void replay_event_net_save(void *opaque)
>       NetEvent *event = opaque;
>   
>       replay_put_byte(event->id);
> -    replay_put_dword(event->flags);
>       replay_put_array(event->data, event->size);
>   }
>   
> @@ -94,7 +91,6 @@ void *replay_event_net_load(void)
>       NetEvent *event = g_new(NetEvent, 1);
>   
>       event->id = replay_get_byte();
> -    event->flags = replay_get_dword();
>       replay_get_array_alloc(&event->data, &event->size);
>   
>       return event;



^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 06/21] net: Remove flag propagation
  2023-11-10  7:35   ` Pavel Dovgalyuk
@ 2023-11-11 14:27     ` Akihiko Odaki
  2023-11-13  8:14       ` Pavel Dovgalyuk
  0 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-11-11 14:27 UTC (permalink / raw)
  To: Pavel Dovgalyuk
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Pavel Dovgalyuk, Paolo Bonzini,
	Zhang Chen, Li Zhijian

On 2023/11/10 16:35, Pavel Dovgalyuk wrote:
> You need to bump REPLAY_VERSION in replay/replay.c, because your patch 
> changes the replay log format.
> 
> Otherwise, for replay part:
> Acked-by: Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>

I'll drop this change then. It's just a cleanup and does not bring an 
additional benefit worth breaking the log format.


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-03 13:14                                   ` Yuri Benditovich
@ 2023-11-11 15:28                                     ` Akihiko Odaki
  2023-11-13 11:44                                       ` Yuri Benditovich
  0 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-11-11 15:28 UTC (permalink / raw)
  To: Yuri Benditovich
  Cc: Michael S. Tsirkin, Jason Wang, qemu-devel, Andrew Melnychenko

On 2023/11/03 22:14, Yuri Benditovich wrote:
> 
> 
> On Fri, Nov 3, 2023 at 11:55 AM Akihiko Odaki <akihiko.odaki@daynix.com 
> <mailto:akihiko.odaki@daynix.com>> wrote:
> 
>     On 2023/11/03 18:35, Yuri Benditovich wrote:
>      >
>      >
>      > On Thu, Nov 2, 2023 at 4:56 PM Akihiko Odaki
>     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
>      > <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>> wrote:
>      >
>      >     On 2023/11/02 19:20, Yuri Benditovich wrote:
>      >      >
>      >      >
>      >      > On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin
>      >     <mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >      > <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>> wrote:
>      >      >
>      >      >     On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri
>     Benditovich wrote:
>      >      >      > Probably we mix two different patches in this
>     discussion.
>      >      >      > Focusing on the patch in the e-mail header:
>      >      >      >
>      >      >      > IMO it is not acceptable to fail QEMU run for one
>     feature
>      >     that we
>      >      >     can't make
>      >      >      > active when we silently drop all other features in
>     such a
>      >     case.
>      >      >
>      >      >     If the feature is off by default then it seems more
>     reasonable
>      >      >     and silent masking can be seen as a bug.
>      >      >     Most virtio features are on by default this is why it's
>      >      >     reasonable to mask them.
>      >      >
>      >      >
>      >      > If we are talking about RSS: setting it initially off is the
>      >     development
>      >      > time decision.
>      >      > When it will be completely stable there is no reason to
>     keep it
>      >     off by
>      >      > default, so this is more a question of time and of a
>     readiness of
>      >     libvirt.
>      >
>      >     It is not ok to make "on" the default; that will enable RSS
>     even when
>      >     eBPF steering support is not present and can result in
>     performance
>      >     degradation.
>      >
>      >
>      > Exactly as it is today - with vhost=on the host does not suggest RSS
>      > without  eBPF.
>      > I do not understand what you call "performance degradation", can you
>      > describe the scenario?
> 
>     I was not clear, but I was talking about the case of vhost=off or peers
>     other than tap (e.g., user). rss=on employs in-qemu RSS, which incurs
>     overheads for such configurations.
> 
> 
> So, vhost=off OR peers other than tap:
> 
> In the case of peers other than tap (IMO) we're not talking about 
> performance at all.
> Backends like "user" (without vnet_hdr) do not support _many_ 
> performance-oriented features.
> If RSS is somehow "supported" for such backends this is rather a 
> misunderstanding (IMO again).

We do not need to ensure good performance when RSS is enabled by the 
guest for backends without eBPF steering program as you say. In-QEMU RSS 
is only useful for testing and not meant to improve the performance.

However, if you set rss=on, QEMU will advertise the availability of RSS 
feature. The guest will have no mean to know if it's implemented in a 
way not performance-wise so it may decide to use the feature to improve 
the performance, which can result in performance degradation. Therefore, 
it's better not to set rss=on for such backends.


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 06/21] net: Remove flag propagation
  2023-11-11 14:27     ` Akihiko Odaki
@ 2023-11-13  8:14       ` Pavel Dovgalyuk
  0 siblings, 0 replies; 59+ messages in thread
From: Pavel Dovgalyuk @ 2023-11-13  8:14 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: qemu-devel, Yuri Benditovich, Andrew Melnychenko,
	Michael S . Tsirkin, Jason Wang, Paolo Bonzini, Zhang Chen,
	Li Zhijian

On 11.11.2023 17:27, Akihiko Odaki wrote:
> On 2023/11/10 16:35, Pavel Dovgalyuk wrote:
>> You need to bump REPLAY_VERSION in replay/replay.c, because your patch 
>> changes the replay log format.
>>
>> Otherwise, for replay part:
>> Acked-by: Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
> 
> I'll drop this change then. It's just a cleanup and does not bring an 
> additional benefit worth breaking the log format.

Breaking the log format is ok, because replays may be incompatible for 
different builds, because peripheral or vCPU behavior may change.

So bumping the version just helps with not replaying the wrong log.


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-11 15:28                                     ` Akihiko Odaki
@ 2023-11-13 11:44                                       ` Yuri Benditovich
  2023-11-13 12:44                                         ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Yuri Benditovich @ 2023-11-13 11:44 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Michael S. Tsirkin, Jason Wang, qemu-devel, Andrew Melnychenko

[-- Attachment #1: Type: text/plain, Size: 4127 bytes --]

On Sat, Nov 11, 2023 at 5:28 PM Akihiko Odaki <akihiko.odaki@daynix.com>
wrote:

> On 2023/11/03 22:14, Yuri Benditovich wrote:
> >
> >
> > On Fri, Nov 3, 2023 at 11:55 AM Akihiko Odaki <akihiko.odaki@daynix.com
> > <mailto:akihiko.odaki@daynix.com>> wrote:
> >
> >     On 2023/11/03 18:35, Yuri Benditovich wrote:
> >      >
> >      >
> >      > On Thu, Nov 2, 2023 at 4:56 PM Akihiko Odaki
> >     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
> >      > <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>> wrote:
> >      >
> >      >     On 2023/11/02 19:20, Yuri Benditovich wrote:
> >      >      >
> >      >      >
> >      >      > On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin
> >      >     <mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >      > <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>> wrote:
> >      >      >
> >      >      >     On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri
> >     Benditovich wrote:
> >      >      >      > Probably we mix two different patches in this
> >     discussion.
> >      >      >      > Focusing on the patch in the e-mail header:
> >      >      >      >
> >      >      >      > IMO it is not acceptable to fail QEMU run for one
> >     feature
> >      >     that we
> >      >      >     can't make
> >      >      >      > active when we silently drop all other features in
> >     such a
> >      >     case.
> >      >      >
> >      >      >     If the feature is off by default then it seems more
> >     reasonable
> >      >      >     and silent masking can be seen as a bug.
> >      >      >     Most virtio features are on by default this is why it's
> >      >      >     reasonable to mask them.
> >      >      >
> >      >      >
> >      >      > If we are talking about RSS: setting it initially off is
> the
> >      >     development
> >      >      > time decision.
> >      >      > When it will be completely stable there is no reason to
> >     keep it
> >      >     off by
> >      >      > default, so this is more a question of time and of a
> >     readiness of
> >      >     libvirt.
> >      >
> >      >     It is not ok to make "on" the default; that will enable RSS
> >     even when
> >      >     eBPF steering support is not present and can result in
> >     performance
> >      >     degradation.
> >      >
> >      >
> >      > Exactly as it is today - with vhost=on the host does not suggest
> RSS
> >      > without  eBPF.
> >      > I do not understand what you call "performance degradation", can
> you
> >      > describe the scenario?
> >
> >     I was not clear, but I was talking about the case of vhost=off or
> peers
> >     other than tap (e.g., user). rss=on employs in-qemu RSS, which incurs
> >     overheads for such configurations.
> >
> >
> > So, vhost=off OR peers other than tap:
> >
> > In the case of peers other than tap (IMO) we're not talking about
> > performance at all.
> > Backends like "user" (without vnet_hdr) do not support _many_
> > performance-oriented features.
> > If RSS is somehow "supported" for such backends this is rather a
> > misunderstanding (IMO again).
>
> We do not need to ensure good performance when RSS is enabled by the
> guest for backends without eBPF steering program as you say. In-QEMU RSS
> is only useful for testing and not meant to improve the performance.
>
> However, if you set rss=on, QEMU will advertise the availability of RSS
> feature. The guest will have no mean to know if it's implemented in a
> way not performance-wise so it may decide to use the feature to improve
> the performance, which can result in performance degradation. Therefore,
> it's better not to set rss=on for such backends.
>

I still do not understand what is the scenario where you see or suspect the
mentioned "performance degradation".
We can discuss whether such a problem exists as soon as you explain it.

[-- Attachment #2: Type: text/html, Size: 6389 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-13 11:44                                       ` Yuri Benditovich
@ 2023-11-13 12:44                                         ` Akihiko Odaki
  2023-11-13 17:26                                           ` Yuri Benditovich
  0 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-11-13 12:44 UTC (permalink / raw)
  To: Yuri Benditovich
  Cc: Michael S. Tsirkin, Jason Wang, qemu-devel, Andrew Melnychenko

On 2023/11/13 20:44, Yuri Benditovich wrote:
> 
> 
> On Sat, Nov 11, 2023 at 5:28 PM Akihiko Odaki <akihiko.odaki@daynix.com 
> <mailto:akihiko.odaki@daynix.com>> wrote:
> 
>     On 2023/11/03 22:14, Yuri Benditovich wrote:
>      >
>      >
>      > On Fri, Nov 3, 2023 at 11:55 AM Akihiko Odaki
>     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
>      > <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>> wrote:
>      >
>      >     On 2023/11/03 18:35, Yuri Benditovich wrote:
>      >      >
>      >      >
>      >      > On Thu, Nov 2, 2023 at 4:56 PM Akihiko Odaki
>      >     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
>     <mailto:akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>>
>      >      > <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>>> wrote:
>      >      >
>      >      >     On 2023/11/02 19:20, Yuri Benditovich wrote:
>      >      >      >
>      >      >      >
>      >      >      > On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin
>      >      >     <mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
>      >      >      > <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>> wrote:
>      >      >      >
>      >      >      >     On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri
>      >     Benditovich wrote:
>      >      >      >      > Probably we mix two different patches in this
>      >     discussion.
>      >      >      >      > Focusing on the patch in the e-mail header:
>      >      >      >      >
>      >      >      >      > IMO it is not acceptable to fail QEMU run
>     for one
>      >     feature
>      >      >     that we
>      >      >      >     can't make
>      >      >      >      > active when we silently drop all other
>     features in
>      >     such a
>      >      >     case.
>      >      >      >
>      >      >      >     If the feature is off by default then it seems more
>      >     reasonable
>      >      >      >     and silent masking can be seen as a bug.
>      >      >      >     Most virtio features are on by default this is
>     why it's
>      >      >      >     reasonable to mask them.
>      >      >      >
>      >      >      >
>      >      >      > If we are talking about RSS: setting it initially
>     off is the
>      >      >     development
>      >      >      > time decision.
>      >      >      > When it will be completely stable there is no reason to
>      >     keep it
>      >      >     off by
>      >      >      > default, so this is more a question of time and of a
>      >     readiness of
>      >      >     libvirt.
>      >      >
>      >      >     It is not ok to make "on" the default; that will
>     enable RSS
>      >     even when
>      >      >     eBPF steering support is not present and can result in
>      >     performance
>      >      >     degradation.
>      >      >
>      >      >
>      >      > Exactly as it is today - with vhost=on the host does not
>     suggest RSS
>      >      > without  eBPF.
>      >      > I do not understand what you call "performance
>     degradation", can you
>      >      > describe the scenario?
>      >
>      >     I was not clear, but I was talking about the case of
>     vhost=off or peers
>      >     other than tap (e.g., user). rss=on employs in-qemu RSS,
>     which incurs
>      >     overheads for such configurations.
>      >
>      >
>      > So, vhost=off OR peers other than tap:
>      >
>      > In the case of peers other than tap (IMO) we're not talking about
>      > performance at all.
>      > Backends like "user" (without vnet_hdr) do not support _many_
>      > performance-oriented features.
>      > If RSS is somehow "supported" for such backends this is rather a
>      > misunderstanding (IMO again).
> 
>     We do not need to ensure good performance when RSS is enabled by the
>     guest for backends without eBPF steering program as you say. In-QEMU
>     RSS
>     is only useful for testing and not meant to improve the performance.
> 
>     However, if you set rss=on, QEMU will advertise the availability of RSS
>     feature. The guest will have no mean to know if it's implemented in a
>     way not performance-wise so it may decide to use the feature to improve
>     the performance, which can result in performance degradation.
>     Therefore,
>     it's better not to set rss=on for such backends.
> 
> 
> I still do not understand what is the scenario where you see or suspect 
> the mentioned "performance degradation".
> We can discuss whether such a problem exists as soon as you explain it.

The scenario is that:
- rss=on,
- A backend without eBPF steering support is in use, and
- The guest expects VIRTIO_NET_F_RSS has little overheads as hardware 
RSS implementations do.

I consider the risk of the performance degradation in such a situation 
is the reason why virtio-net emits a warning ("Can't load eBPF RSS - 
fallback to software RSS") when in-QEMU RSS is in use.


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-13 12:44                                         ` Akihiko Odaki
@ 2023-11-13 17:26                                           ` Yuri Benditovich
  2023-11-14  7:03                                             ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Yuri Benditovich @ 2023-11-13 17:26 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Michael S. Tsirkin, Jason Wang, qemu-devel, Andrew Melnychenko

[-- Attachment #1: Type: text/plain, Size: 6227 bytes --]

On Mon, Nov 13, 2023 at 2:44 PM Akihiko Odaki <akihiko.odaki@daynix.com>
wrote:

> On 2023/11/13 20:44, Yuri Benditovich wrote:
> >
> >
> > On Sat, Nov 11, 2023 at 5:28 PM Akihiko Odaki <akihiko.odaki@daynix.com
> > <mailto:akihiko.odaki@daynix.com>> wrote:
> >
> >     On 2023/11/03 22:14, Yuri Benditovich wrote:
> >      >
> >      >
> >      > On Fri, Nov 3, 2023 at 11:55 AM Akihiko Odaki
> >     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
> >      > <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>> wrote:
> >      >
> >      >     On 2023/11/03 18:35, Yuri Benditovich wrote:
> >      >      >
> >      >      >
> >      >      > On Thu, Nov 2, 2023 at 4:56 PM Akihiko Odaki
> >      >     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
> >     <mailto:akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>>
> >      >      > <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>>> wrote:
> >      >      >
> >      >      >     On 2023/11/02 19:20, Yuri Benditovich wrote:
> >      >      >      >
> >      >      >      >
> >      >      >      > On Thu, Nov 2, 2023 at 11:33 AM Michael S. Tsirkin
> >      >      >     <mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
> >      >      >      > <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>> wrote:
> >      >      >      >
> >      >      >      >     On Thu, Nov 02, 2023 at 11:09:27AM +0200, Yuri
> >      >     Benditovich wrote:
> >      >      >      >      > Probably we mix two different patches in this
> >      >     discussion.
> >      >      >      >      > Focusing on the patch in the e-mail header:
> >      >      >      >      >
> >      >      >      >      > IMO it is not acceptable to fail QEMU run
> >     for one
> >      >     feature
> >      >      >     that we
> >      >      >      >     can't make
> >      >      >      >      > active when we silently drop all other
> >     features in
> >      >     such a
> >      >      >     case.
> >      >      >      >
> >      >      >      >     If the feature is off by default then it seems
> more
> >      >     reasonable
> >      >      >      >     and silent masking can be seen as a bug.
> >      >      >      >     Most virtio features are on by default this is
> >     why it's
> >      >      >      >     reasonable to mask them.
> >      >      >      >
> >      >      >      >
> >      >      >      > If we are talking about RSS: setting it initially
> >     off is the
> >      >      >     development
> >      >      >      > time decision.
> >      >      >      > When it will be completely stable there is no
> reason to
> >      >     keep it
> >      >      >     off by
> >      >      >      > default, so this is more a question of time and of a
> >      >     readiness of
> >      >      >     libvirt.
> >      >      >
> >      >      >     It is not ok to make "on" the default; that will
> >     enable RSS
> >      >     even when
> >      >      >     eBPF steering support is not present and can result in
> >      >     performance
> >      >      >     degradation.
> >      >      >
> >      >      >
> >      >      > Exactly as it is today - with vhost=on the host does not
> >     suggest RSS
> >      >      > without  eBPF.
> >      >      > I do not understand what you call "performance
> >     degradation", can you
> >      >      > describe the scenario?
> >      >
> >      >     I was not clear, but I was talking about the case of
> >     vhost=off or peers
> >      >     other than tap (e.g., user). rss=on employs in-qemu RSS,
> >     which incurs
> >      >     overheads for such configurations.
> >      >
> >      >
> >      > So, vhost=off OR peers other than tap:
> >      >
> >      > In the case of peers other than tap (IMO) we're not talking about
> >      > performance at all.
> >      > Backends like "user" (without vnet_hdr) do not support _many_
> >      > performance-oriented features.
> >      > If RSS is somehow "supported" for such backends this is rather a
> >      > misunderstanding (IMO again).
> >
> >     We do not need to ensure good performance when RSS is enabled by the
> >     guest for backends without eBPF steering program as you say. In-QEMU
> >     RSS
> >     is only useful for testing and not meant to improve the performance.
> >
> >     However, if you set rss=on, QEMU will advertise the availability of
> RSS
> >     feature. The guest will have no mean to know if it's implemented in a
> >     way not performance-wise so it may decide to use the feature to
> improve
> >     the performance, which can result in performance degradation.
> >     Therefore,
> >     it's better not to set rss=on for such backends.
> >
> >
> > I still do not understand what is the scenario where you see or suspect
> > the mentioned "performance degradation".
> > We can discuss whether such a problem exists as soon as you explain it.
>
> The scenario is that:
> - rss=on,
> - A backend without eBPF steering support is in use, and
> - The guest expects VIRTIO_NET_F_RSS has little overheads as hardware
> RSS implementations do.
>
> I consider the risk of the performance degradation in such a situation
> is the reason why virtio-net emits a warning ("Can't load eBPF RSS -
> fallback to software RSS") when in-QEMU RSS is in use.
>

In a described scenario (vhost=off) I do not see why the performance
degradation should happen:
the SW RSS (if activated) will place each packet into proper queue (even if
the auto_mq in kernel is not able to do that) and such a way the guest will
not need to reschedule the packet to proper CPU

[-- Attachment #2: Type: text/html, Size: 10253 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-13 17:26                                           ` Yuri Benditovich
@ 2023-11-14  7:03                                             ` Akihiko Odaki
  2023-11-14 22:09                                               ` Yuri Benditovich
  0 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-11-14  7:03 UTC (permalink / raw)
  To: Andrew Melnychenko, Yuri Benditovich
  Cc: Michael S. Tsirkin, Jason Wang, qemu-devel

On 2023/11/14 2:26, Yuri Benditovich wrote:
> 
> 
> On Mon, Nov 13, 2023 at 2:44 PM Akihiko Odaki <akihiko.odaki@daynix.com 
> <mailto:akihiko.odaki@daynix.com>> wrote:
> 
>     On 2023/11/13 20:44, Yuri Benditovich wrote:
>      >
>      >
>      > On Sat, Nov 11, 2023 at 5:28 PM Akihiko Odaki
>     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
>      > <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>> wrote:
>      >
>      >     On 2023/11/03 22:14, Yuri Benditovich wrote:
>      >      >
>      >      >
>      >      > On Fri, Nov 3, 2023 at 11:55 AM Akihiko Odaki
>      >     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
>     <mailto:akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>>
>      >      > <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>>> wrote:
>      >      >
>      >      >     On 2023/11/03 18:35, Yuri Benditovich wrote:
>      >      >      >
>      >      >      >
>      >      >      > On Thu, Nov 2, 2023 at 4:56 PM Akihiko Odaki
>      >      >     <akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com> <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com> <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>>
>      >      >      > <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>
>      >      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>>>> wrote:
>      >      >      >
>      >      >      >     On 2023/11/02 19:20, Yuri Benditovich wrote:
>      >      >      >      >
>      >      >      >      >
>      >      >      >      > On Thu, Nov 2, 2023 at 11:33 AM Michael S.
>     Tsirkin
>      >      >      >     <mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
>      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>
>      >      >      >      > <mailto:mst@redhat.com
>     <mailto:mst@redhat.com> <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
>      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>>> wrote:
>      >      >      >      >
>      >      >      >      >     On Thu, Nov 02, 2023 at 11:09:27AM
>     +0200, Yuri
>      >      >     Benditovich wrote:
>      >      >      >      >      > Probably we mix two different patches
>     in this
>      >      >     discussion.
>      >      >      >      >      > Focusing on the patch in the e-mail
>     header:
>      >      >      >      >      >
>      >      >      >      >      > IMO it is not acceptable to fail QEMU run
>      >     for one
>      >      >     feature
>      >      >      >     that we
>      >      >      >      >     can't make
>      >      >      >      >      > active when we silently drop all other
>      >     features in
>      >      >     such a
>      >      >      >     case.
>      >      >      >      >
>      >      >      >      >     If the feature is off by default then it
>     seems more
>      >      >     reasonable
>      >      >      >      >     and silent masking can be seen as a bug.
>      >      >      >      >     Most virtio features are on by default
>     this is
>      >     why it's
>      >      >      >      >     reasonable to mask them.
>      >      >      >      >
>      >      >      >      >
>      >      >      >      > If we are talking about RSS: setting it
>     initially
>      >     off is the
>      >      >      >     development
>      >      >      >      > time decision.
>      >      >      >      > When it will be completely stable there is
>     no reason to
>      >      >     keep it
>      >      >      >     off by
>      >      >      >      > default, so this is more a question of time
>     and of a
>      >      >     readiness of
>      >      >      >     libvirt.
>      >      >      >
>      >      >      >     It is not ok to make "on" the default; that will
>      >     enable RSS
>      >      >     even when
>      >      >      >     eBPF steering support is not present and can
>     result in
>      >      >     performance
>      >      >      >     degradation.
>      >      >      >
>      >      >      >
>      >      >      > Exactly as it is today - with vhost=on the host
>     does not
>      >     suggest RSS
>      >      >      > without  eBPF.
>      >      >      > I do not understand what you call "performance
>      >     degradation", can you
>      >      >      > describe the scenario?
>      >      >
>      >      >     I was not clear, but I was talking about the case of
>      >     vhost=off or peers
>      >      >     other than tap (e.g., user). rss=on employs in-qemu RSS,
>      >     which incurs
>      >      >     overheads for such configurations.
>      >      >
>      >      >
>      >      > So, vhost=off OR peers other than tap:
>      >      >
>      >      > In the case of peers other than tap (IMO) we're not
>     talking about
>      >      > performance at all.
>      >      > Backends like "user" (without vnet_hdr) do not support _many_
>      >      > performance-oriented features.
>      >      > If RSS is somehow "supported" for such backends this is
>     rather a
>      >      > misunderstanding (IMO again).
>      >
>      >     We do not need to ensure good performance when RSS is enabled
>     by the
>      >     guest for backends without eBPF steering program as you say.
>     In-QEMU
>      >     RSS
>      >     is only useful for testing and not meant to improve the
>     performance.
>      >
>      >     However, if you set rss=on, QEMU will advertise the
>     availability of RSS
>      >     feature. The guest will have no mean to know if it's
>     implemented in a
>      >     way not performance-wise so it may decide to use the feature
>     to improve
>      >     the performance, which can result in performance degradation.
>      >     Therefore,
>      >     it's better not to set rss=on for such backends.
>      >
>      >
>      > I still do not understand what is the scenario where you see or
>     suspect
>      > the mentioned "performance degradation".
>      > We can discuss whether such a problem exists as soon as you
>     explain it.
> 
>     The scenario is that:
>     - rss=on,
>     - A backend without eBPF steering support is in use, and
>     - The guest expects VIRTIO_NET_F_RSS has little overheads as hardware
>     RSS implementations do.
> 
>     I consider the risk of the performance degradation in such a situation
>     is the reason why virtio-net emits a warning ("Can't load eBPF RSS -
>     fallback to software RSS") when in-QEMU RSS is in use.
> 
> 
> In a described scenario (vhost=off) I do not see why the performance 
> degradation should happen:
> the SW RSS (if activated) will place each packet into proper queue (even 
> if the auto_mq in kernel is not able to do that) and such a way the 
> guest will not need to reschedule the packet to proper CPU
> 

The scenario I'm concerned is that the guest has its own packet steering 
mechanism which is feature-wise superior to RSS. For example, Linux has 
such a mechanism called RPS, which has some advantages due to its 
extensible nature according to:
https://www.kernel.org/doc/html/v6.6/networking/scaling.html#rps-receive-packet-steering

Such a guest may still prefer hardware RSS if available since hardware 
RSS is expected to have less overheads. However, it is not true for 
in-qemu RSS, and using in-QEMU RSS instead of the guest-side steering 
mechanism may just hide useful features the guest-side steering 
mechanism has and result in performance degradation.

Andrew, I appreciate if you also tell the rationale behind the warning 
you put for software RSS ("Can't load eBPF RSS - fallback to software RSS").


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-14  7:03                                             ` Akihiko Odaki
@ 2023-11-14 22:09                                               ` Yuri Benditovich
  2023-11-15  6:09                                                 ` Akihiko Odaki
  0 siblings, 1 reply; 59+ messages in thread
From: Yuri Benditovich @ 2023-11-14 22:09 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Andrew Melnychenko, Michael S. Tsirkin, Jason Wang, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 9737 bytes --]

On Tue, Nov 14, 2023 at 9:03 AM Akihiko Odaki <akihiko.odaki@daynix.com>
wrote:

> On 2023/11/14 2:26, Yuri Benditovich wrote:
> >
> >
> > On Mon, Nov 13, 2023 at 2:44 PM Akihiko Odaki <akihiko.odaki@daynix.com
> > <mailto:akihiko.odaki@daynix.com>> wrote:
> >
> >     On 2023/11/13 20:44, Yuri Benditovich wrote:
> >      >
> >      >
> >      > On Sat, Nov 11, 2023 at 5:28 PM Akihiko Odaki
> >     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
> >      > <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>> wrote:
> >      >
> >      >     On 2023/11/03 22:14, Yuri Benditovich wrote:
> >      >      >
> >      >      >
> >      >      > On Fri, Nov 3, 2023 at 11:55 AM Akihiko Odaki
> >      >     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
> >     <mailto:akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>>
> >      >      > <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>>> wrote:
> >      >      >
> >      >      >     On 2023/11/03 18:35, Yuri Benditovich wrote:
> >      >      >      >
> >      >      >      >
> >      >      >      > On Thu, Nov 2, 2023 at 4:56 PM Akihiko Odaki
> >      >      >     <akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com> <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com> <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>>
> >      >      >      > <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>
> >      >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>>>> wrote:
> >      >      >      >
> >      >      >      >     On 2023/11/02 19:20, Yuri Benditovich wrote:
> >      >      >      >      >
> >      >      >      >      >
> >      >      >      >      > On Thu, Nov 2, 2023 at 11:33 AM Michael S.
> >     Tsirkin
> >      >      >      >     <mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
> >      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>
> >      >      >      >      > <mailto:mst@redhat.com
> >     <mailto:mst@redhat.com> <mailto:mst@redhat.com <mailto:
> mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
> >      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>>> wrote:
> >      >      >      >      >
> >      >      >      >      >     On Thu, Nov 02, 2023 at 11:09:27AM
> >     +0200, Yuri
> >      >      >     Benditovich wrote:
> >      >      >      >      >      > Probably we mix two different patches
> >     in this
> >      >      >     discussion.
> >      >      >      >      >      > Focusing on the patch in the e-mail
> >     header:
> >      >      >      >      >      >
> >      >      >      >      >      > IMO it is not acceptable to fail QEMU
> run
> >      >     for one
> >      >      >     feature
> >      >      >      >     that we
> >      >      >      >      >     can't make
> >      >      >      >      >      > active when we silently drop all other
> >      >     features in
> >      >      >     such a
> >      >      >      >     case.
> >      >      >      >      >
> >      >      >      >      >     If the feature is off by default then it
> >     seems more
> >      >      >     reasonable
> >      >      >      >      >     and silent masking can be seen as a bug.
> >      >      >      >      >     Most virtio features are on by default
> >     this is
> >      >     why it's
> >      >      >      >      >     reasonable to mask them.
> >      >      >      >      >
> >      >      >      >      >
> >      >      >      >      > If we are talking about RSS: setting it
> >     initially
> >      >     off is the
> >      >      >      >     development
> >      >      >      >      > time decision.
> >      >      >      >      > When it will be completely stable there is
> >     no reason to
> >      >      >     keep it
> >      >      >      >     off by
> >      >      >      >      > default, so this is more a question of time
> >     and of a
> >      >      >     readiness of
> >      >      >      >     libvirt.
> >      >      >      >
> >      >      >      >     It is not ok to make "on" the default; that will
> >      >     enable RSS
> >      >      >     even when
> >      >      >      >     eBPF steering support is not present and can
> >     result in
> >      >      >     performance
> >      >      >      >     degradation.
> >      >      >      >
> >      >      >      >
> >      >      >      > Exactly as it is today - with vhost=on the host
> >     does not
> >      >     suggest RSS
> >      >      >      > without  eBPF.
> >      >      >      > I do not understand what you call "performance
> >      >     degradation", can you
> >      >      >      > describe the scenario?
> >      >      >
> >      >      >     I was not clear, but I was talking about the case of
> >      >     vhost=off or peers
> >      >      >     other than tap (e.g., user). rss=on employs in-qemu
> RSS,
> >      >     which incurs
> >      >      >     overheads for such configurations.
> >      >      >
> >      >      >
> >      >      > So, vhost=off OR peers other than tap:
> >      >      >
> >      >      > In the case of peers other than tap (IMO) we're not
> >     talking about
> >      >      > performance at all.
> >      >      > Backends like "user" (without vnet_hdr) do not support
> _many_
> >      >      > performance-oriented features.
> >      >      > If RSS is somehow "supported" for such backends this is
> >     rather a
> >      >      > misunderstanding (IMO again).
> >      >
> >      >     We do not need to ensure good performance when RSS is enabled
> >     by the
> >      >     guest for backends without eBPF steering program as you say.
> >     In-QEMU
> >      >     RSS
> >      >     is only useful for testing and not meant to improve the
> >     performance.
> >      >
> >      >     However, if you set rss=on, QEMU will advertise the
> >     availability of RSS
> >      >     feature. The guest will have no mean to know if it's
> >     implemented in a
> >      >     way not performance-wise so it may decide to use the feature
> >     to improve
> >      >     the performance, which can result in performance degradation.
> >      >     Therefore,
> >      >     it's better not to set rss=on for such backends.
> >      >
> >      >
> >      > I still do not understand what is the scenario where you see or
> >     suspect
> >      > the mentioned "performance degradation".
> >      > We can discuss whether such a problem exists as soon as you
> >     explain it.
> >
> >     The scenario is that:
> >     - rss=on,
> >     - A backend without eBPF steering support is in use, and
> >     - The guest expects VIRTIO_NET_F_RSS has little overheads as hardware
> >     RSS implementations do.
> >
> >     I consider the risk of the performance degradation in such a
> situation
> >     is the reason why virtio-net emits a warning ("Can't load eBPF RSS -
> >     fallback to software RSS") when in-QEMU RSS is in use.
> >
> >
> > In a described scenario (vhost=off) I do not see why the performance
> > degradation should happen:
> > the SW RSS (if activated) will place each packet into proper queue (even
> > if the auto_mq in kernel is not able to do that) and such a way the
> > guest will not need to reschedule the packet to proper CPU
> >
>
> The scenario I'm concerned is that the guest has its own packet steering
> mechanism which is feature-wise superior to RSS. For example, Linux has
> such a mechanism called RPS, which has some advantages due to its
> extensible nature according to:
>
> https://www.kernel.org/doc/html/v6.6/networking/scaling.html#rps-receive-packet-steering
>
> Such a guest may still prefer hardware RSS if available since hardware
> RSS is expected to have less overheads. However, it is not true for
> in-qemu RSS, and using in-QEMU RSS instead of the guest-side steering
> mechanism may just hide useful features the guest-side steering
> mechanism has and result in performance degradation.
>

Note that in terms of per-packet computation for RSS the in-QEMU RSS does
exactly the same operations in native code that the eBPF does in the
emulation.
So, I wouldn't say that SW RSS brings some "performance degradation".
We prefer eBPF as it can serve both vhost and non-vhost setups.


> Andrew, I appreciate if you also tell the rationale behind the warning
> you put for software RSS ("Can't load eBPF RSS - fallback to software
> RSS").
>

[-- Attachment #2: Type: text/html, Size: 17292 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-14 22:09                                               ` Yuri Benditovich
@ 2023-11-15  6:09                                                 ` Akihiko Odaki
  2023-11-16  5:14                                                   ` Jason Wang
  0 siblings, 1 reply; 59+ messages in thread
From: Akihiko Odaki @ 2023-11-15  6:09 UTC (permalink / raw)
  To: Jason Wang, Yuri Benditovich
  Cc: Andrew Melnychenko, Michael S. Tsirkin, qemu-devel



On 2023/11/15 7:09, Yuri Benditovich wrote:
> 
> 
> On Tue, Nov 14, 2023 at 9:03 AM Akihiko Odaki <akihiko.odaki@daynix.com 
> <mailto:akihiko.odaki@daynix.com>> wrote:
> 
>     On 2023/11/14 2:26, Yuri Benditovich wrote:
>      >
>      >
>      > On Mon, Nov 13, 2023 at 2:44 PM Akihiko Odaki
>     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
>      > <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>> wrote:
>      >
>      >     On 2023/11/13 20:44, Yuri Benditovich wrote:
>      >      >
>      >      >
>      >      > On Sat, Nov 11, 2023 at 5:28 PM Akihiko Odaki
>      >     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
>     <mailto:akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>>
>      >      > <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>>> wrote:
>      >      >
>      >      >     On 2023/11/03 22:14, Yuri Benditovich wrote:
>      >      >      >
>      >      >      >
>      >      >      > On Fri, Nov 3, 2023 at 11:55 AM Akihiko Odaki
>      >      >     <akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com> <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com> <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>>
>      >      >      > <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>
>      >      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>>>> wrote:
>      >      >      >
>      >      >      >     On 2023/11/03 18:35, Yuri Benditovich wrote:
>      >      >      >      >
>      >      >      >      >
>      >      >      >      > On Thu, Nov 2, 2023 at 4:56 PM Akihiko Odaki
>      >      >      >     <akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>> <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>>
>      >      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>> <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>>>
>      >      >      >      > <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>
>      >      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>>
>      >      >      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>
>      >      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>
>      >     <mailto:akihiko.odaki@daynix.com
>     <mailto:akihiko.odaki@daynix.com>>>>>> wrote:
>      >      >      >      >
>      >      >      >      >     On 2023/11/02 19:20, Yuri Benditovich wrote:
>      >      >      >      >      >
>      >      >      >      >      >
>      >      >      >      >      > On Thu, Nov 2, 2023 at 11:33 AM
>     Michael S.
>      >     Tsirkin
>      >      >      >      >     <mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
>      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>
>      >      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
>      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>>
>      >      >      >      >      > <mailto:mst@redhat.com
>     <mailto:mst@redhat.com>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
>      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>
>      >      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
>      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
>      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
>     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>>>> wrote:
>      >      >      >      >      >
>      >      >      >      >      >     On Thu, Nov 02, 2023 at 11:09:27AM
>      >     +0200, Yuri
>      >      >      >     Benditovich wrote:
>      >      >      >      >      >      > Probably we mix two different
>     patches
>      >     in this
>      >      >      >     discussion.
>      >      >      >      >      >      > Focusing on the patch in the
>     e-mail
>      >     header:
>      >      >      >      >      >      >
>      >      >      >      >      >      > IMO it is not acceptable to
>     fail QEMU run
>      >      >     for one
>      >      >      >     feature
>      >      >      >      >     that we
>      >      >      >      >      >     can't make
>      >      >      >      >      >      > active when we silently drop
>     all other
>      >      >     features in
>      >      >      >     such a
>      >      >      >      >     case.
>      >      >      >      >      >
>      >      >      >      >      >     If the feature is off by default
>     then it
>      >     seems more
>      >      >      >     reasonable
>      >      >      >      >      >     and silent masking can be seen as
>     a bug.
>      >      >      >      >      >     Most virtio features are on by
>     default
>      >     this is
>      >      >     why it's
>      >      >      >      >      >     reasonable to mask them.
>      >      >      >      >      >
>      >      >      >      >      >
>      >      >      >      >      > If we are talking about RSS: setting it
>      >     initially
>      >      >     off is the
>      >      >      >      >     development
>      >      >      >      >      > time decision.
>      >      >      >      >      > When it will be completely stable
>     there is
>      >     no reason to
>      >      >      >     keep it
>      >      >      >      >     off by
>      >      >      >      >      > default, so this is more a question
>     of time
>      >     and of a
>      >      >      >     readiness of
>      >      >      >      >     libvirt.
>      >      >      >      >
>      >      >      >      >     It is not ok to make "on" the default;
>     that will
>      >      >     enable RSS
>      >      >      >     even when
>      >      >      >      >     eBPF steering support is not present and can
>      >     result in
>      >      >      >     performance
>      >      >      >      >     degradation.
>      >      >      >      >
>      >      >      >      >
>      >      >      >      > Exactly as it is today - with vhost=on the host
>      >     does not
>      >      >     suggest RSS
>      >      >      >      > without  eBPF.
>      >      >      >      > I do not understand what you call "performance
>      >      >     degradation", can you
>      >      >      >      > describe the scenario?
>      >      >      >
>      >      >      >     I was not clear, but I was talking about the
>     case of
>      >      >     vhost=off or peers
>      >      >      >     other than tap (e.g., user). rss=on employs
>     in-qemu RSS,
>      >      >     which incurs
>      >      >      >     overheads for such configurations.
>      >      >      >
>      >      >      >
>      >      >      > So, vhost=off OR peers other than tap:
>      >      >      >
>      >      >      > In the case of peers other than tap (IMO) we're not
>      >     talking about
>      >      >      > performance at all.
>      >      >      > Backends like "user" (without vnet_hdr) do not
>     support _many_
>      >      >      > performance-oriented features.
>      >      >      > If RSS is somehow "supported" for such backends this is
>      >     rather a
>      >      >      > misunderstanding (IMO again).
>      >      >
>      >      >     We do not need to ensure good performance when RSS is
>     enabled
>      >     by the
>      >      >     guest for backends without eBPF steering program as
>     you say.
>      >     In-QEMU
>      >      >     RSS
>      >      >     is only useful for testing and not meant to improve the
>      >     performance.
>      >      >
>      >      >     However, if you set rss=on, QEMU will advertise the
>      >     availability of RSS
>      >      >     feature. The guest will have no mean to know if it's
>      >     implemented in a
>      >      >     way not performance-wise so it may decide to use the
>     feature
>      >     to improve
>      >      >     the performance, which can result in performance
>     degradation.
>      >      >     Therefore,
>      >      >     it's better not to set rss=on for such backends.
>      >      >
>      >      >
>      >      > I still do not understand what is the scenario where you
>     see or
>      >     suspect
>      >      > the mentioned "performance degradation".
>      >      > We can discuss whether such a problem exists as soon as you
>      >     explain it.
>      >
>      >     The scenario is that:
>      >     - rss=on,
>      >     - A backend without eBPF steering support is in use, and
>      >     - The guest expects VIRTIO_NET_F_RSS has little overheads as
>     hardware
>      >     RSS implementations do.
>      >
>      >     I consider the risk of the performance degradation in such a
>     situation
>      >     is the reason why virtio-net emits a warning ("Can't load
>     eBPF RSS -
>      >     fallback to software RSS") when in-QEMU RSS is in use.
>      >
>      >
>      > In a described scenario (vhost=off) I do not see why the performance
>      > degradation should happen:
>      > the SW RSS (if activated) will place each packet into proper
>     queue (even
>      > if the auto_mq in kernel is not able to do that) and such a way the
>      > guest will not need to reschedule the packet to proper CPU
>      >
> 
>     The scenario I'm concerned is that the guest has its own packet
>     steering
>     mechanism which is feature-wise superior to RSS. For example, Linux has
>     such a mechanism called RPS, which has some advantages due to its
>     extensible nature according to:
>     https://www.kernel.org/doc/html/v6.6/networking/scaling.html#rps-receive-packet-steering <https://www.kernel.org/doc/html/v6.6/networking/scaling.html#rps-receive-packet-steering>
> 
>     Such a guest may still prefer hardware RSS if available since hardware
>     RSS is expected to have less overheads. However, it is not true for
>     in-qemu RSS, and using in-QEMU RSS instead of the guest-side steering
>     mechanism may just hide useful features the guest-side steering
>     mechanism has and result in performance degradation.
> 
> 
> Note that in terms of per-packet computation for RSS the in-QEMU RSS 
> does exactly the same operations in native code that the eBPF does in 
> the emulation.
> So, I wouldn't say that SW RSS brings some "performance degradation".
> We prefer eBPF as it can serve both vhost and non-vhost setups.

I see the eBPF steering program in a different way.

tuntap can have several queues, and the assignment of packets is 
automatically done by tuntap by default. However, the default assignment 
policy may not be good for all applications, and some may need a 
different policy. Such an application can still re-assign packets to 
application-internal queues that reside on different CPUs and that's 
what 'in-qemu' RSS does. However, that incurs communication overheads 
across CPUs. The eBPF steering program can eliminate the overheads by 
allowing the userspace to override the packet assignment policy with eBPF.

The eBPF steering program feature of tuntap and its benefit are 
independent of the vhost usage. In fact, the feature predates the usage 
in QEMU that combines vhost and eBPF steering program. The initial 
proposal of the eBPF steering program I found is submitted by Jason and 
available at:
https://lore.kernel.org/lkml/1506500637-13881-1-git-send-email-jasowang@redhat.com/

Jason, please point out if you find something wrong in my understanding 
with the eBPF steering program feature or something to add.


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS
  2023-11-15  6:09                                                 ` Akihiko Odaki
@ 2023-11-16  5:14                                                   ` Jason Wang
  0 siblings, 0 replies; 59+ messages in thread
From: Jason Wang @ 2023-11-16  5:14 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Yuri Benditovich, Andrew Melnychenko, Michael S. Tsirkin, qemu-devel

On Wed, Nov 15, 2023 at 2:09 PM Akihiko Odaki <akihiko.odaki@daynix.com> wrote:
>
>
>
> On 2023/11/15 7:09, Yuri Benditovich wrote:
> >
> >
> > On Tue, Nov 14, 2023 at 9:03 AM Akihiko Odaki <akihiko.odaki@daynix.com
> > <mailto:akihiko.odaki@daynix.com>> wrote:
> >
> >     On 2023/11/14 2:26, Yuri Benditovich wrote:
> >      >
> >      >
> >      > On Mon, Nov 13, 2023 at 2:44 PM Akihiko Odaki
> >     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
> >      > <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>> wrote:
> >      >
> >      >     On 2023/11/13 20:44, Yuri Benditovich wrote:
> >      >      >
> >      >      >
> >      >      > On Sat, Nov 11, 2023 at 5:28 PM Akihiko Odaki
> >      >     <akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>
> >     <mailto:akihiko.odaki@daynix.com <mailto:akihiko.odaki@daynix.com>>
> >      >      > <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>>> wrote:
> >      >      >
> >      >      >     On 2023/11/03 22:14, Yuri Benditovich wrote:
> >      >      >      >
> >      >      >      >
> >      >      >      > On Fri, Nov 3, 2023 at 11:55 AM Akihiko Odaki
> >      >      >     <akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com> <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com> <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>>
> >      >      >      > <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>
> >      >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>>>> wrote:
> >      >      >      >
> >      >      >      >     On 2023/11/03 18:35, Yuri Benditovich wrote:
> >      >      >      >      >
> >      >      >      >      >
> >      >      >      >      > On Thu, Nov 2, 2023 at 4:56 PM Akihiko Odaki
> >      >      >      >     <akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>> <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>>
> >      >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>> <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>>>
> >      >      >      >      > <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>
> >      >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>>
> >      >      >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>
> >      >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>
> >      >     <mailto:akihiko.odaki@daynix.com
> >     <mailto:akihiko.odaki@daynix.com>>>>>> wrote:
> >      >      >      >      >
> >      >      >      >      >     On 2023/11/02 19:20, Yuri Benditovich wrote:
> >      >      >      >      >      >
> >      >      >      >      >      >
> >      >      >      >      >      > On Thu, Nov 2, 2023 at 11:33 AM
> >     Michael S.
> >      >     Tsirkin
> >      >      >      >      >     <mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
> >      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>
> >      >      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
> >      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>>
> >      >      >      >      >      > <mailto:mst@redhat.com
> >     <mailto:mst@redhat.com>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
> >      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>
> >      >      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>
> >      >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>
> >      >     <mailto:mst@redhat.com <mailto:mst@redhat.com>
> >     <mailto:mst@redhat.com <mailto:mst@redhat.com>>>>>>> wrote:
> >      >      >      >      >      >
> >      >      >      >      >      >     On Thu, Nov 02, 2023 at 11:09:27AM
> >      >     +0200, Yuri
> >      >      >      >     Benditovich wrote:
> >      >      >      >      >      >      > Probably we mix two different
> >     patches
> >      >     in this
> >      >      >      >     discussion.
> >      >      >      >      >      >      > Focusing on the patch in the
> >     e-mail
> >      >     header:
> >      >      >      >      >      >      >
> >      >      >      >      >      >      > IMO it is not acceptable to
> >     fail QEMU run
> >      >      >     for one
> >      >      >      >     feature
> >      >      >      >      >     that we
> >      >      >      >      >      >     can't make
> >      >      >      >      >      >      > active when we silently drop
> >     all other
> >      >      >     features in
> >      >      >      >     such a
> >      >      >      >      >     case.
> >      >      >      >      >      >
> >      >      >      >      >      >     If the feature is off by default
> >     then it
> >      >     seems more
> >      >      >      >     reasonable
> >      >      >      >      >      >     and silent masking can be seen as
> >     a bug.
> >      >      >      >      >      >     Most virtio features are on by
> >     default
> >      >     this is
> >      >      >     why it's
> >      >      >      >      >      >     reasonable to mask them.
> >      >      >      >      >      >
> >      >      >      >      >      >
> >      >      >      >      >      > If we are talking about RSS: setting it
> >      >     initially
> >      >      >     off is the
> >      >      >      >      >     development
> >      >      >      >      >      > time decision.
> >      >      >      >      >      > When it will be completely stable
> >     there is
> >      >     no reason to
> >      >      >      >     keep it
> >      >      >      >      >     off by
> >      >      >      >      >      > default, so this is more a question
> >     of time
> >      >     and of a
> >      >      >      >     readiness of
> >      >      >      >      >     libvirt.
> >      >      >      >      >
> >      >      >      >      >     It is not ok to make "on" the default;
> >     that will
> >      >      >     enable RSS
> >      >      >      >     even when
> >      >      >      >      >     eBPF steering support is not present and can
> >      >     result in
> >      >      >      >     performance
> >      >      >      >      >     degradation.
> >      >      >      >      >
> >      >      >      >      >
> >      >      >      >      > Exactly as it is today - with vhost=on the host
> >      >     does not
> >      >      >     suggest RSS
> >      >      >      >      > without  eBPF.
> >      >      >      >      > I do not understand what you call "performance
> >      >      >     degradation", can you
> >      >      >      >      > describe the scenario?
> >      >      >      >
> >      >      >      >     I was not clear, but I was talking about the
> >     case of
> >      >      >     vhost=off or peers
> >      >      >      >     other than tap (e.g., user). rss=on employs
> >     in-qemu RSS,
> >      >      >     which incurs
> >      >      >      >     overheads for such configurations.
> >      >      >      >
> >      >      >      >
> >      >      >      > So, vhost=off OR peers other than tap:
> >      >      >      >
> >      >      >      > In the case of peers other than tap (IMO) we're not
> >      >     talking about
> >      >      >      > performance at all.
> >      >      >      > Backends like "user" (without vnet_hdr) do not
> >     support _many_
> >      >      >      > performance-oriented features.
> >      >      >      > If RSS is somehow "supported" for such backends this is
> >      >     rather a
> >      >      >      > misunderstanding (IMO again).
> >      >      >
> >      >      >     We do not need to ensure good performance when RSS is
> >     enabled
> >      >     by the
> >      >      >     guest for backends without eBPF steering program as
> >     you say.
> >      >     In-QEMU
> >      >      >     RSS
> >      >      >     is only useful for testing and not meant to improve the
> >      >     performance.
> >      >      >
> >      >      >     However, if you set rss=on, QEMU will advertise the
> >      >     availability of RSS
> >      >      >     feature. The guest will have no mean to know if it's
> >      >     implemented in a
> >      >      >     way not performance-wise so it may decide to use the
> >     feature
> >      >     to improve
> >      >      >     the performance, which can result in performance
> >     degradation.
> >      >      >     Therefore,
> >      >      >     it's better not to set rss=on for such backends.
> >      >      >
> >      >      >
> >      >      > I still do not understand what is the scenario where you
> >     see or
> >      >     suspect
> >      >      > the mentioned "performance degradation".
> >      >      > We can discuss whether such a problem exists as soon as you
> >      >     explain it.
> >      >
> >      >     The scenario is that:
> >      >     - rss=on,
> >      >     - A backend without eBPF steering support is in use, and
> >      >     - The guest expects VIRTIO_NET_F_RSS has little overheads as
> >     hardware
> >      >     RSS implementations do.
> >      >
> >      >     I consider the risk of the performance degradation in such a
> >     situation
> >      >     is the reason why virtio-net emits a warning ("Can't load
> >     eBPF RSS -
> >      >     fallback to software RSS") when in-QEMU RSS is in use.
> >      >
> >      >
> >      > In a described scenario (vhost=off) I do not see why the performance
> >      > degradation should happen:
> >      > the SW RSS (if activated) will place each packet into proper
> >     queue (even
> >      > if the auto_mq in kernel is not able to do that) and such a way the
> >      > guest will not need to reschedule the packet to proper CPU
> >      >
> >
> >     The scenario I'm concerned is that the guest has its own packet
> >     steering
> >     mechanism which is feature-wise superior to RSS. For example, Linux has
> >     such a mechanism called RPS, which has some advantages due to its
> >     extensible nature according to:
> >     https://www.kernel.org/doc/html/v6.6/networking/scaling.html#rps-receive-packet-steering <https://www.kernel.org/doc/html/v6.6/networking/scaling.html#rps-receive-packet-steering>
> >
> >     Such a guest may still prefer hardware RSS if available since hardware
> >     RSS is expected to have less overheads. However, it is not true for
> >     in-qemu RSS, and using in-QEMU RSS instead of the guest-side steering
> >     mechanism may just hide useful features the guest-side steering
> >     mechanism has and result in performance degradation.
> >
> >
> > Note that in terms of per-packet computation for RSS the in-QEMU RSS
> > does exactly the same operations in native code that the eBPF does in
> > the emulation.
> > So, I wouldn't say that SW RSS brings some "performance degradation".
> > We prefer eBPF as it can serve both vhost and non-vhost setups.
>
> I see the eBPF steering program in a different way.
>
> tuntap can have several queues,

Note that RSS can benefit for single queue as well.

> and the assignment of packets is
> automatically done by tuntap by default. However, the default assignment
> policy may not be good for all applications, and some may need a
> different policy. Such an application can still re-assign packets to
> application-internal queues that reside on different CPUs and that's
> what 'in-qemu' RSS does. However, that incurs communication overheads
> across CPUs. The eBPF steering program can eliminate the overheads by
> allowing the userspace to override the packet assignment policy with eBPF.
>

Yes, eBPF steering can do more than just RSS. For VM use cases, it
just needs to wait for the spec support. For example, spec will
support receiving flow director soon, we can leverage the eBPF support
for tuntap to do that.

> The eBPF steering program feature of tuntap and its benefit are
> independent of the vhost usage. In fact, the feature predates the usage
> in QEMU that combines vhost and eBPF steering program.

I think they should coexist. For example, for many reasons eBPF might
not be available on the host.

> The initial
> proposal of the eBPF steering program I found is submitted by Jason and
> available at:
> https://lore.kernel.org/lkml/1506500637-13881-1-git-send-email-jasowang@redhat.com/
>
> Jason, please point out if you find something wrong in my understanding
> with the eBPF steering program feature or something to add.

Thanks

>



^ permalink raw reply	[flat|nested] 59+ messages in thread

end of thread, other threads:[~2023-11-16  5:16 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-30  5:12 [PATCH v6 00/21] virtio-net RSS/hash report fixes and improvements Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 01/21] tap: Remove tap_probe_vnet_hdr_len() Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 02/21] tap: Remove qemu_using_vnet_hdr() Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 03/21] net: Move virtio-net header length assertion Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 04/21] net: Remove receive_raw() Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 05/21] tap: Remove tap_receive() Akihiko Odaki
2023-10-30 18:52   ` Zhang, Chen
2023-10-31  4:57     ` Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 06/21] net: Remove flag propagation Akihiko Odaki
2023-11-10  7:35   ` Pavel Dovgalyuk
2023-11-11 14:27     ` Akihiko Odaki
2023-11-13  8:14       ` Pavel Dovgalyuk
2023-10-30  5:12 ` [PATCH v6 07/21] tap: Shrink zeroed virtio-net header Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 08/21] virtio-net: Copy header only when necessary Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 09/21] virtio-net: Disable RSS on reset Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 10/21] virtio-net: Unify the logic to update NIC state for RSS Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 11/21] virtio-net: Return an error when vhost cannot enable RSS Akihiko Odaki
2023-10-30 12:14   ` Yuri Benditovich
2023-10-30 12:21     ` Akihiko Odaki
2023-10-30 12:51       ` Yuri Benditovich
2023-10-30 13:14         ` Akihiko Odaki
2023-11-01  4:19           ` Jason Wang
2023-11-01  4:50             ` Akihiko Odaki
2023-11-01  6:38               ` Michael S. Tsirkin
2023-11-01  8:35                 ` Akihiko Odaki
2023-11-01  9:09                   ` Michael S. Tsirkin
2023-11-01  9:15                     ` Akihiko Odaki
2023-11-02  9:09                       ` Yuri Benditovich
2023-11-02  9:33                         ` Michael S. Tsirkin
2023-11-02 10:20                           ` Yuri Benditovich
2023-11-02 11:26                             ` Michael S. Tsirkin
2023-11-02 12:00                               ` Yuri Benditovich
2023-11-02 13:18                                 ` Michael S. Tsirkin
2023-11-02 14:56                             ` Akihiko Odaki
2023-11-03  9:35                               ` Yuri Benditovich
2023-11-03  9:55                                 ` Akihiko Odaki
2023-11-03 13:14                                   ` Yuri Benditovich
2023-11-11 15:28                                     ` Akihiko Odaki
2023-11-13 11:44                                       ` Yuri Benditovich
2023-11-13 12:44                                         ` Akihiko Odaki
2023-11-13 17:26                                           ` Yuri Benditovich
2023-11-14  7:03                                             ` Akihiko Odaki
2023-11-14 22:09                                               ` Yuri Benditovich
2023-11-15  6:09                                                 ` Akihiko Odaki
2023-11-16  5:14                                                   ` Jason Wang
2023-10-30  5:12 ` [PATCH v6 12/21] virtio-net: Enable software RSS Akihiko Odaki
2023-10-30 12:42   ` Yuri Benditovich
2023-10-30  5:12 ` [PATCH v6 13/21] virtio-net: Always set populate_hash Akihiko Odaki
2023-10-30 19:02   ` Zhang, Chen
2023-10-31  4:47     ` Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 14/21] virtio-net: Do not write hashes to peer buffer Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 15/21] virtio-net: Do not clear VIRTIO_NET_F_HASH_REPORT Akihiko Odaki
2023-11-03 13:26   ` Yuri Benditovich
2023-10-30  5:12 ` [PATCH v6 16/21] ebpf: Fix RSS error handling Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 17/21] ebpf: Use standard section name Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 18/21] ebpf: Simplify error handling Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 19/21] ebpf: Return 0 when configuration fails Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 20/21] ebpf: Refactor tun_rss_steering_prog() Akihiko Odaki
2023-10-30  5:12 ` [PATCH v6 21/21] ebpf: Add a separate target for skeleton Akihiko Odaki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.