From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 7919F42CC2; Thu, 15 Jun 2023 08:30:52 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 067B040DDA; Thu, 15 Jun 2023 08:30:52 +0200 (CEST) Received: from mail-yw1-f177.google.com (mail-yw1-f177.google.com [209.85.128.177]) by mails.dpdk.org (Postfix) with ESMTP id 1867140A84 for ; Thu, 15 Jun 2023 08:30:51 +0200 (CEST) Received: by mail-yw1-f177.google.com with SMTP id 00721157ae682-56ce96063bcso7189317b3.1 for ; Wed, 14 Jun 2023 23:30:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1686810650; x=1689402650; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=UscAKHVf7hMBfib5Tf3WHzANOpoJ5uIHBdFiON4yIOw=; b=aQruELPUOABNDh8ie5aG/sFHcy2F2cNGEPN78JLNOrabpwp28bwBhfWqtREHHivvW2 KTUsRw6XADjrmT9qmBP7cfLJUy0bkkLrscjUdhuswkx1c7vymA8QoY5LAEruz/IzRXfw jS454sxXAkUm+X9+Sz/JdBg/XxbkIHylbZs57HtKPNIgj3w2iWKtAcxGmQNSP9oKypYu 2tCSVdL64Sr2tElkfCitVF+y18QBv8PVzW6mPO9y8cLd3D7FcjrDzJjsxX7SNrfxZtEd Dtahej0Ey7sBHtNSu4tHxC3Dkb0wqSi3dPwewMnJYWpCjkHLiKsZAyGgI/jdyEL0VnNs FspA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686810650; x=1689402650; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=UscAKHVf7hMBfib5Tf3WHzANOpoJ5uIHBdFiON4yIOw=; b=mFIFbWVHA/DQC/ofW/1JzGc4X72Z/8PxviBbceWqrkhX03DsHhbWHQLJj+zgbpR7zr KDtz4wgWdqkoo6JIcgoT+UtL4ZBNh7+4W5YEv2mzgwG1DUUHSu1TDCe9+kwZrVV166+l i/vwGzFFoZkRVvuAtYnNtAuytUwPTIdI67Z78OdfEdVDQxcFqxu/JX3qRsDZ6rl0XFj/ qs3khs/39OiqdpBnE2mTnG9Hj5Drk3RzOG1IRHj3N8Yw67pudAZl2+nUN7Az7VZiAVZL 7HClP9ZHpiylWLd/VlzXTrjVrg/laAqu/pBB0FeFWERBYCHZJeduDH1FCOkkdz+BN/+g MHZw== X-Gm-Message-State: AC+VfDwFM009KOOq4L9GYc6/fShbqzOiPHDOPY/QxMu8T8iGABJUrwEc M2gXQskqh2JFxBIgphV3joVmULU/XbLDSs6Pw+IH5ycH X-Google-Smtp-Source: ACHHUZ7fkdQk/2Hkg9CF7azQQVpGPs4WMU+IFLe4oxUL16TGk7pjxAYIVLzbSm+TSKYW007M7amT/pTYoT7Q8xr1+mM= X-Received: by 2002:a0d:cbcb:0:b0:56c:e5a3:3e09 with SMTP id n194-20020a0dcbcb000000b0056ce5a33e09mr4811685ywd.15.1686810649895; Wed, 14 Jun 2023 23:30:49 -0700 (PDT) MIME-Version: 1.0 References: <20221020181425.48006-1-kumaraparmesh92@gmail.com> <20230615062028.22773-1-kumaraparamesh92@gmail.com> In-Reply-To: <20230615062028.22773-1-kumaraparamesh92@gmail.com> From: kumaraparameshwaran rathinavel Date: Thu, 15 Jun 2023 12:00:38 +0530 Message-ID: Subject: Re: [PATCH v9] gro : ipv6 changes to support GRO for TCP/ipv6 To: jiayu.hu@intel.com Cc: dev@dpdk.org Content-Type: multipart/alternative; boundary="00000000000097279c05fe2535f0" X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org --00000000000097279c05fe2535f0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Thu, Jun 15, 2023 at 11:50=E2=80=AFAM Kumara Parameshwaran < kumaraparamesh92@gmail.com> wrote: > The patch adds GRO support for TCP/ipv6 packets. This does not > include the support for vxlan, udp ipv6 packets. > > Signed-off-by: Kumara Parameshwaran > --- > v1: > * Changes to support GRO for TCP/ipv6 packets. This does not > include > vxlan changes. > * The GRO is performed only for ipv6 packets that does not contai= n > extension headers. > * The logic for the TCP coalescing remains the same, in ipv6 > header > the source address, destination address, flow label, version > fields > are expected to be the same. > * Re-organised the code to reuse certain tcp functions for both > ipv4 and > ipv6 flows. > v2: > * Fix comments in gro_tcp6.h header file. > > v3: > * Adderess review comments to fix code duplication for v4 and v6 > > v4: > * Addresses review comments for v3, do not use callbacks > > v5: > * Address review comments > > v6: > * Fix warning and coding style issues > > v7: > * Fix build compilation issue > > v8: > * Use gro_tcp_internal.h for functions used for gro_tcp4 and > gro_tcp6 and use > gro_tcp.h for data structures and functions used across > gro_vxlan_tcp4 > > v9: > * Resolve merge conflict and add gro_tcp.h in proper path > > .../generic_receive_offload_lib.rst | 21 +- > doc/guides/rel_notes/release_23_07.rst | 2 + > lib/gro/gro_tcp.h | 187 ++++++++++++ > lib/gro/gro_tcp4.c | 177 +++--------- > lib/gro/gro_tcp4.h | 170 +---------- > lib/gro/gro_tcp6.c | 268 ++++++++++++++++++ > lib/gro/gro_tcp6.h | 160 +++++++++++ > lib/gro/gro_tcp_internal.h | 128 +++++++++ > lib/gro/gro_vxlan_tcp4.c | 22 +- > lib/gro/gro_vxlan_tcp4.h | 2 +- > lib/gro/meson.build | 1 + > lib/gro/rte_gro.c | 83 +++++- > lib/gro/rte_gro.h | 3 + > 13 files changed, 883 insertions(+), 341 deletions(-) > create mode 100644 lib/gro/gro_tcp.h > create mode 100644 lib/gro/gro_tcp6.c > create mode 100644 lib/gro/gro_tcp6.h > create mode 100644 lib/gro/gro_tcp_internal.h > > diff --git a/doc/guides/prog_guide/generic_receive_offload_lib.rst > b/doc/guides/prog_guide/generic_receive_offload_lib.rst > index 98a5d29bbc..533cda7f5c 100644 > --- a/doc/guides/prog_guide/generic_receive_offload_lib.rst > +++ b/doc/guides/prog_guide/generic_receive_offload_lib.rst > @@ -138,20 +138,21 @@ The key-based algorithm has two characters: > > Key-based Reassembly Algorithm > > -TCP/IPv4 GRO > ------------- > +TCP-IPv4/IPv6 GRO > +----------------- > > -The table structure used by TCP/IPv4 GRO contains two arrays: flow array > +The table structure used by TCP-IPv4/IPv6 GRO contains two arrays: flow > array > and item array. The flow array keeps flow information, and the item arra= y > -keeps packet information. > +keeps packet information. The flow array is different for IPv4 and IPv6 > while > +the item array is the same. > > -Header fields used to define a TCP/IPv4 flow include: > +Header fields used to define a TCP-IPv4/IPv6 flow include: > > -- source and destination: Ethernet and IP address, TCP port > +- common tcp key fields : Ethernet address, TCP port, TCP acknowledge > number > +- version specific IP address > +- IPv6 flow label for IPv6 flow > > -- TCP acknowledge number > - > -TCP/IPv4 packets whose FIN, SYN, RST, URG, PSH, ECE or CWR bit is set > +TCP packets whose FIN, SYN, RST, URG, PSH, ECE or CWR bit is set > won't be processed. > > Header fields deciding if two packets are neighbors include: > @@ -159,7 +160,7 @@ Header fields deciding if two packets are neighbors > include: > - TCP sequence number > > - IPv4 ID. The IPv4 ID fields of the packets, whose DF bit is 0, should > - be increased by 1. > + be increased by 1. This is applicable only for IPv4 > > VxLAN GRO > --------- > diff --git a/doc/guides/rel_notes/release_23_07.rst > b/doc/guides/rel_notes/release_23_07.rst > index 027ae7bd2d..7124cf45c7 100644 > --- a/doc/guides/rel_notes/release_23_07.rst > +++ b/doc/guides/rel_notes/release_23_07.rst > @@ -170,6 +170,8 @@ New Features > > See :doc:`../prog_guide/pdcp_lib` for more information. > > +* **Added support for TCP/IPv6 GRO.** > + * Enhanced the existing library to support GRO for TCP packets over > IPv6 network. > > Removed Items > ------------- > diff --git a/lib/gro/gro_tcp.h b/lib/gro/gro_tcp.h > new file mode 100644 > index 0000000000..7c7a6a3008 > --- /dev/null > +++ b/lib/gro/gro_tcp.h > @@ -0,0 +1,187 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2023 Intel Corporation > + */ > +#ifndef _GRO_TCP_H_ > +#define _GRO_TCP_H_ > + > +#define INVALID_ARRAY_INDEX 0xffffffffUL > + > +#include > + > +/* > + * The max length of a IPv4 packet, which includes the length of the L3 > + * header, the L4 header and the data payload. > + */ > +#define MAX_IP_PKT_LENGTH UINT16_MAX > + > +/* The maximum TCP header length */ > +#define MAX_TCP_HLEN 60 > +#define INVALID_TCP_HDRLEN(len) \ > + (((len) < sizeof(struct rte_tcp_hdr)) || ((len) > MAX_TCP_HLEN)) > + > +struct cmn_tcp_key { > + struct rte_ether_addr eth_saddr; > + struct rte_ether_addr eth_daddr; > + uint32_t recv_ack; > + uint16_t src_port; > + uint16_t dst_port; > +}; > + > +#define ASSIGN_COMMON_TCP_KEY(k1, k2) \ > + do {\ > + rte_ether_addr_copy(&(k1->eth_saddr), &(k2->eth_saddr)); = \ > + rte_ether_addr_copy(&(k1->eth_daddr), &(k2->eth_daddr)); = \ > + k2->recv_ack =3D k1->recv_ack; \ > + k2->src_port =3D k1->src_port; \ > + k2->dst_port =3D k1->dst_port; \ > + } while (0) > + > +struct gro_tcp_item { > + /* > + * The first MBUF segment of the packet. If the value > + * is NULL, it means the item is empty. > + */ > + struct rte_mbuf *firstseg; > + /* The last MBUF segment of the packet */ > + struct rte_mbuf *lastseg; > + /* > + * The time when the first packet is inserted into the table. > + * This value won't be updated, even if the packet is merged > + * with other packets. > + */ > + uint64_t start_time; > + /* > + * next_pkt_idx is used to chain the packets that > + * are in the same flow but can't be merged together > + * (e.g. caused by packet reordering). > + */ > + uint32_t next_pkt_idx; > + /* TCP sequence number of the packet */ > + uint32_t sent_seq; > + union { > + /* IPv4 ID of the packet */ > + uint16_t ip_id; > + /* Unused field for IPv6 */ > + uint16_t unused; > + } l3; > + /* the number of merged packets */ > + uint16_t nb_merged; > + /* Indicate if IPv4 ID can be ignored */ > + uint8_t is_atomic; > +}; > + > +/* > + * Merge two TCP packets without updating checksums. > + * If cmp is larger than 0, append the new packet to the > + * original packet. Otherwise, pre-pend the new packet to > + * the original packet. > + */ > +static inline int > +merge_two_tcp_packets(struct gro_tcp_item *item, > + struct rte_mbuf *pkt, > + int cmp, > + uint32_t sent_seq, > + uint16_t ip_id, > + uint16_t l2_offset) > +{ > + struct rte_mbuf *pkt_head, *pkt_tail, *lastseg; > + uint16_t hdr_len, l2_len; > + > + if (cmp > 0) { > + pkt_head =3D item->firstseg; > + pkt_tail =3D pkt; > + } else { > + pkt_head =3D pkt; > + pkt_tail =3D item->firstseg; > + } > + > + /* check if the IPv4 packet length is greater than the max value = */ > + hdr_len =3D l2_offset + pkt_head->l2_len + pkt_head->l3_len + > + pkt_head->l4_len; > + l2_len =3D l2_offset > 0 ? pkt_head->outer_l2_len : pkt_head->l2_= len; > + if (unlikely(pkt_head->pkt_len - l2_len + pkt_tail->pkt_len - > + hdr_len > MAX_IP_PKT_LENGTH)) > + return 0; > + > + /* remove the packet header for the tail packet */ > + rte_pktmbuf_adj(pkt_tail, hdr_len); > + > + /* chain two packets together */ > + if (cmp > 0) { > + item->lastseg->next =3D pkt; > + item->lastseg =3D rte_pktmbuf_lastseg(pkt); > + /* update IP ID to the larger value */ > + item->l3.ip_id =3D ip_id; > + } else { > + lastseg =3D rte_pktmbuf_lastseg(pkt); > + lastseg->next =3D item->firstseg; > + item->firstseg =3D pkt; > + /* update sent_seq to the smaller value */ > + item->sent_seq =3D sent_seq; > + item->l3.ip_id =3D ip_id; > + } > + item->nb_merged++; > + > + /* update MBUF metadata for the merged packet */ > + pkt_head->nb_segs +=3D pkt_tail->nb_segs; > + pkt_head->pkt_len +=3D pkt_tail->pkt_len; > + > + return 1; > +} > + > +/* > + * Check if two TCP packets are neighbors. > + */ > +static inline int > +check_seq_option(struct gro_tcp_item *item, > + struct rte_tcp_hdr *tcph, > + uint32_t sent_seq, > + uint16_t ip_id, > + uint16_t tcp_hl, > + uint16_t tcp_dl, > + uint16_t l2_offset, > + uint8_t is_atomic) > +{ > + struct rte_mbuf *pkt_orig =3D item->firstseg; > + char *iph_orig; > + struct rte_tcp_hdr *tcph_orig; > + uint16_t len, tcp_hl_orig; > + > + iph_orig =3D (char *)(rte_pktmbuf_mtod(pkt_orig, char *) + > + l2_offset + pkt_orig->l2_len); > + tcph_orig =3D (struct rte_tcp_hdr *)(iph_orig + pkt_orig->l3_len)= ; > + tcp_hl_orig =3D pkt_orig->l4_len; > + > + /* Check if TCP option fields equal */ > + len =3D RTE_MAX(tcp_hl, tcp_hl_orig) - sizeof(struct rte_tcp_hdr)= ; > + if ((tcp_hl !=3D tcp_hl_orig) || ((len > 0) && > + (memcmp(tcph + 1, tcph_orig + 1, > + len) !=3D 0))) > + return 0; > + > + /* Don't merge packets whose DF bits are different */ > + if (unlikely(item->is_atomic ^ is_atomic)) > + return 0; > + > + /* check if the two packets are neighbors */ > + len =3D pkt_orig->pkt_len - l2_offset - pkt_orig->l2_len - > + pkt_orig->l3_len - tcp_hl_orig; > + if ((sent_seq =3D=3D item->sent_seq + len) && (is_atomic || > + (ip_id =3D=3D item->l3.ip_id + 1))) > + /* append the new packet */ > + return 1; > + else if ((sent_seq + tcp_dl =3D=3D item->sent_seq) && (is_atomic = || > + (ip_id + item->nb_merged =3D=3D > item->l3.ip_id))) > + /* pre-pend the new packet */ > + return -1; > + > + return 0; > +} > + > +static inline int > +is_same_common_tcp_key(struct cmn_tcp_key *k1, struct cmn_tcp_key *k2) > +{ > + return (!memcmp(k1, k2, sizeof(struct cmn_tcp_key))); > +} > + > +#endif > diff --git a/lib/gro/gro_tcp4.c b/lib/gro/gro_tcp4.c > index 0014096e63..6645de592b 100644 > --- a/lib/gro/gro_tcp4.c > +++ b/lib/gro/gro_tcp4.c > @@ -7,6 +7,7 @@ > #include > > #include "gro_tcp4.h" > +#include "gro_tcp_internal.h" > > void * > gro_tcp4_tbl_create(uint16_t socket_id, > @@ -30,7 +31,7 @@ gro_tcp4_tbl_create(uint16_t socket_id, > if (tbl =3D=3D NULL) > return NULL; > > - size =3D sizeof(struct gro_tcp4_item) * entries_num; > + size =3D sizeof(struct gro_tcp_item) * entries_num; > tbl->items =3D rte_zmalloc_socket(__func__, > size, > RTE_CACHE_LINE_SIZE, > @@ -71,18 +72,6 @@ gro_tcp4_tbl_destroy(void *tbl) > rte_free(tcp_tbl); > } > > -static inline uint32_t > -find_an_empty_item(struct gro_tcp4_tbl *tbl) > -{ > - uint32_t i; > - uint32_t max_item_num =3D tbl->max_item_num; > - > - for (i =3D 0; i < max_item_num; i++) > - if (tbl->items[i].firstseg =3D=3D NULL) > - return i; > - return INVALID_ARRAY_INDEX; > -} > - > static inline uint32_t > find_an_empty_flow(struct gro_tcp4_tbl *tbl) > { > @@ -95,56 +84,6 @@ find_an_empty_flow(struct gro_tcp4_tbl *tbl) > return INVALID_ARRAY_INDEX; > } > > -static inline uint32_t > -insert_new_item(struct gro_tcp4_tbl *tbl, > - struct rte_mbuf *pkt, > - uint64_t start_time, > - uint32_t prev_idx, > - uint32_t sent_seq, > - uint16_t ip_id, > - uint8_t is_atomic) > -{ > - uint32_t item_idx; > - > - item_idx =3D find_an_empty_item(tbl); > - if (item_idx =3D=3D INVALID_ARRAY_INDEX) > - return INVALID_ARRAY_INDEX; > - > - tbl->items[item_idx].firstseg =3D pkt; > - tbl->items[item_idx].lastseg =3D rte_pktmbuf_lastseg(pkt); > - tbl->items[item_idx].start_time =3D start_time; > - tbl->items[item_idx].next_pkt_idx =3D INVALID_ARRAY_INDEX; > - tbl->items[item_idx].sent_seq =3D sent_seq; > - tbl->items[item_idx].ip_id =3D ip_id; > - tbl->items[item_idx].nb_merged =3D 1; > - tbl->items[item_idx].is_atomic =3D is_atomic; > - tbl->item_num++; > - > - /* if the previous packet exists, chain them together. */ > - if (prev_idx !=3D INVALID_ARRAY_INDEX) { > - tbl->items[item_idx].next_pkt_idx =3D > - tbl->items[prev_idx].next_pkt_idx; > - tbl->items[prev_idx].next_pkt_idx =3D item_idx; > - } > - > - return item_idx; > -} > - > -static inline uint32_t > -delete_item(struct gro_tcp4_tbl *tbl, uint32_t item_idx, > - uint32_t prev_item_idx) > -{ > - uint32_t next_idx =3D tbl->items[item_idx].next_pkt_idx; > - > - /* NULL indicates an empty item */ > - tbl->items[item_idx].firstseg =3D NULL; > - tbl->item_num--; > - if (prev_item_idx !=3D INVALID_ARRAY_INDEX) > - tbl->items[prev_item_idx].next_pkt_idx =3D next_idx; > - > - return next_idx; > -} > - > static inline uint32_t > insert_new_flow(struct gro_tcp4_tbl *tbl, > struct tcp4_flow_key *src, > @@ -159,13 +98,10 @@ insert_new_flow(struct gro_tcp4_tbl *tbl, > > dst =3D &(tbl->flows[flow_idx].key); > > - rte_ether_addr_copy(&(src->eth_saddr), &(dst->eth_saddr)); > - rte_ether_addr_copy(&(src->eth_daddr), &(dst->eth_daddr)); > + ASSIGN_COMMON_TCP_KEY((&src->cmn_key), (&dst->cmn_key)); > + > dst->ip_src_addr =3D src->ip_src_addr; > dst->ip_dst_addr =3D src->ip_dst_addr; > - dst->recv_ack =3D src->recv_ack; > - dst->src_port =3D src->src_port; > - dst->dst_port =3D src->dst_port; > > tbl->flows[flow_idx].start_index =3D item_idx; > tbl->flow_num++; > @@ -173,21 +109,6 @@ insert_new_flow(struct gro_tcp4_tbl *tbl, > return flow_idx; > } > > -/* > - * update the packet length for the flushed packet. > - */ > -static inline void > -update_header(struct gro_tcp4_item *item) > -{ > - struct rte_ipv4_hdr *ipv4_hdr; > - struct rte_mbuf *pkt =3D item->firstseg; > - > - ipv4_hdr =3D (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(pkt, char *= ) + > - pkt->l2_len); > - ipv4_hdr->total_length =3D rte_cpu_to_be_16(pkt->pkt_len - > - pkt->l2_len); > -} > - > int32_t > gro_tcp4_reassemble(struct rte_mbuf *pkt, > struct gro_tcp4_tbl *tbl, > @@ -202,9 +123,8 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > uint8_t is_atomic; > > struct tcp4_flow_key key; > - uint32_t cur_idx, prev_idx, item_idx; > + uint32_t item_idx; > uint32_t i, max_flow_num, remaining_flow_num; > - int cmp; > uint8_t find; > > /* > @@ -239,6 +159,14 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > if (tcp_dl <=3D 0) > return -1; > > + rte_ether_addr_copy(&(eth_hdr->src_addr), > &(key.cmn_key.eth_saddr)); > + rte_ether_addr_copy(&(eth_hdr->dst_addr), > &(key.cmn_key.eth_daddr)); > + key.ip_src_addr =3D ipv4_hdr->src_addr; > + key.ip_dst_addr =3D ipv4_hdr->dst_addr; > + key.cmn_key.src_port =3D tcp_hdr->src_port; > + key.cmn_key.dst_port =3D tcp_hdr->dst_port; > + key.cmn_key.recv_ack =3D tcp_hdr->recv_ack; > + > /* > * Save IPv4 ID for the packet whose DF bit is 0. For the packet > * whose DF bit is 1, IPv4 ID is ignored. > @@ -246,15 +174,6 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > frag_off =3D rte_be_to_cpu_16(ipv4_hdr->fragment_offset); > is_atomic =3D (frag_off & RTE_IPV4_HDR_DF_FLAG) =3D=3D > RTE_IPV4_HDR_DF_FLAG; > ip_id =3D is_atomic ? 0 : rte_be_to_cpu_16(ipv4_hdr->packet_id); > - sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > - > - rte_ether_addr_copy(&(eth_hdr->src_addr), &(key.eth_saddr)); > - rte_ether_addr_copy(&(eth_hdr->dst_addr), &(key.eth_daddr)); > - key.ip_src_addr =3D ipv4_hdr->src_addr; > - key.ip_dst_addr =3D ipv4_hdr->dst_addr; > - key.src_port =3D tcp_hdr->src_port; > - key.dst_port =3D tcp_hdr->dst_port; > - key.recv_ack =3D tcp_hdr->recv_ack; > > /* Search for a matched flow. */ > max_flow_num =3D tbl->max_flow_num; > @@ -270,63 +189,44 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > } > } > > - /* > - * Fail to find a matched flow. Insert a new flow and store the > - * packet into the flow. > - */ > if (find =3D=3D 0) { > - item_idx =3D insert_new_item(tbl, pkt, start_time, > - INVALID_ARRAY_INDEX, sent_seq, ip_id, > - is_atomic); > + sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > + item_idx =3D insert_new_tcp_item(pkt, tbl->items, > &tbl->item_num, > + tbl->max_item_num, > start_time, > + INVALID_ARRAY_INDEX, > sent_seq, ip_id, > + is_atomic); > if (item_idx =3D=3D INVALID_ARRAY_INDEX) > return -1; > if (insert_new_flow(tbl, &key, item_idx) =3D=3D > - INVALID_ARRAY_INDEX) { > + INVALID_ARRAY_INDEX) { > /* > * Fail to insert a new flow, so delete the > * stored packet. > - */ > - delete_item(tbl, item_idx, INVALID_ARRAY_INDEX); > + */ > + delete_tcp_item(tbl->items, item_idx, > &tbl->item_num, INVALID_ARRAY_INDEX); > return -1; > } > return 0; > } > > - /* > - * Check all packets in the flow and try to find a neighbor for > - * the input packet. > - */ > - cur_idx =3D tbl->flows[i].start_index; > - prev_idx =3D cur_idx; > - do { > - cmp =3D check_seq_option(&(tbl->items[cur_idx]), tcp_hdr, > - sent_seq, ip_id, pkt->l4_len, tcp_dl, 0, > - is_atomic); > - if (cmp) { > - if (merge_two_tcp4_packets(&(tbl->items[cur_idx])= , > - pkt, cmp, sent_seq, ip_id= , > 0)) > - return 1; > - /* > - * Fail to merge the two packets, as the packet > - * length is greater than the max value. Store > - * the packet into the flow. > - */ > - if (insert_new_item(tbl, pkt, start_time, cur_idx= , > - sent_seq, ip_id, > is_atomic) =3D=3D > - INVALID_ARRAY_INDEX) > - return -1; > - return 0; > - } > - prev_idx =3D cur_idx; > - cur_idx =3D tbl->items[cur_idx].next_pkt_idx; > - } while (cur_idx !=3D INVALID_ARRAY_INDEX); > + return process_tcp_item(pkt, tcp_hdr, tcp_dl, tbl->items, > tbl->flows[i].start_index, > + &tbl->item_num, > tbl->max_item_num, > + ip_id, is_atomic, > start_time); > +} > > - /* Fail to find a neighbor, so store the packet into the flow. */ > - if (insert_new_item(tbl, pkt, start_time, prev_idx, sent_seq, > - ip_id, is_atomic) =3D=3D INVALID_ARRAY_IN= DEX) > - return -1; > +/* > + * update the packet length for the flushed packet. > + */ > +static inline void > +update_header(struct gro_tcp_item *item) > +{ > + struct rte_ipv4_hdr *ipv4_hdr; > + struct rte_mbuf *pkt =3D item->firstseg; > > - return 0; > + ipv4_hdr =3D (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(pkt, char *= ) + > + pkt->l2_len); > + ipv4_hdr->total_length =3D rte_cpu_to_be_16(pkt->pkt_len - > + pkt->l2_len); > } > > uint16_t > @@ -353,7 +253,8 @@ gro_tcp4_tbl_timeout_flush(struct gro_tcp4_tbl *tbl, > * Delete the packet and get the next > * packet in the flow. > */ > - j =3D delete_item(tbl, j, > INVALID_ARRAY_INDEX); > + j =3D delete_tcp_item(tbl->items, j, > + &tbl->item_num, > INVALID_ARRAY_INDEX); > tbl->flows[i].start_index =3D j; > if (j =3D=3D INVALID_ARRAY_INDEX) > tbl->flow_num--; > diff --git a/lib/gro/gro_tcp4.h b/lib/gro/gro_tcp4.h > index 212f97a042..245e5da486 100644 > --- a/lib/gro/gro_tcp4.h > +++ b/lib/gro/gro_tcp4.h > @@ -5,32 +5,15 @@ > #ifndef _GRO_TCP4_H_ > #define _GRO_TCP4_H_ > > -#include > +#include "gro_tcp.h" > > -#define INVALID_ARRAY_INDEX 0xffffffffUL > #define GRO_TCP4_TBL_MAX_ITEM_NUM (1024UL * 1024UL) > > -/* > - * The max length of a IPv4 packet, which includes the length of the L3 > - * header, the L4 header and the data payload. > - */ > -#define MAX_IPV4_PKT_LENGTH UINT16_MAX > - > -/* The maximum TCP header length */ > -#define MAX_TCP_HLEN 60 > -#define INVALID_TCP_HDRLEN(len) \ > - (((len) < sizeof(struct rte_tcp_hdr)) || ((len) > MAX_TCP_HLEN)) > - > -/* Header fields representing a TCP/IPv4 flow */ > +/* Header fields representing common fields in TCP flow */ > struct tcp4_flow_key { > - struct rte_ether_addr eth_saddr; > - struct rte_ether_addr eth_daddr; > + struct cmn_tcp_key cmn_key; > uint32_t ip_src_addr; > uint32_t ip_dst_addr; > - > - uint32_t recv_ack; > - uint16_t src_port; > - uint16_t dst_port; > }; > > struct gro_tcp4_flow { > @@ -42,42 +25,12 @@ struct gro_tcp4_flow { > uint32_t start_index; > }; > > -struct gro_tcp4_item { > - /* > - * The first MBUF segment of the packet. If the value > - * is NULL, it means the item is empty. > - */ > - struct rte_mbuf *firstseg; > - /* The last MBUF segment of the packet */ > - struct rte_mbuf *lastseg; > - /* > - * The time when the first packet is inserted into the table. > - * This value won't be updated, even if the packet is merged > - * with other packets. > - */ > - uint64_t start_time; > - /* > - * next_pkt_idx is used to chain the packets that > - * are in the same flow but can't be merged together > - * (e.g. caused by packet reordering). > - */ > - uint32_t next_pkt_idx; > - /* TCP sequence number of the packet */ > - uint32_t sent_seq; > - /* IPv4 ID of the packet */ > - uint16_t ip_id; > - /* the number of merged packets */ > - uint16_t nb_merged; > - /* Indicate if IPv4 ID can be ignored */ > - uint8_t is_atomic; > -}; > - > /* > * TCP/IPv4 reassembly table structure. > */ > struct gro_tcp4_tbl { > /* item array */ > - struct gro_tcp4_item *items; > + struct gro_tcp_item *items; > /* flow array */ > struct gro_tcp4_flow *flows; > /* current item number */ > @@ -186,120 +139,9 @@ uint32_t gro_tcp4_tbl_pkt_count(void *tbl); > static inline int > is_same_tcp4_flow(struct tcp4_flow_key k1, struct tcp4_flow_key k2) > { > - return (rte_is_same_ether_addr(&k1.eth_saddr, &k2.eth_saddr) && > - rte_is_same_ether_addr(&k1.eth_daddr, > &k2.eth_daddr) && > - (k1.ip_src_addr =3D=3D k2.ip_src_addr) && > + return ((k1.ip_src_addr =3D=3D k2.ip_src_addr) && > (k1.ip_dst_addr =3D=3D k2.ip_dst_addr) && > - (k1.recv_ack =3D=3D k2.recv_ack) && > - (k1.src_port =3D=3D k2.src_port) && > - (k1.dst_port =3D=3D k2.dst_port)); > + is_same_common_tcp_key(&k1.cmn_key, &k2.cmn_key))= ; > } > > -/* > - * Merge two TCP/IPv4 packets without updating checksums. > - * If cmp is larger than 0, append the new packet to the > - * original packet. Otherwise, pre-pend the new packet to > - * the original packet. > - */ > -static inline int > -merge_two_tcp4_packets(struct gro_tcp4_item *item, > - struct rte_mbuf *pkt, > - int cmp, > - uint32_t sent_seq, > - uint16_t ip_id, > - uint16_t l2_offset) > -{ > - struct rte_mbuf *pkt_head, *pkt_tail, *lastseg; > - uint16_t hdr_len, l2_len; > - > - if (cmp > 0) { > - pkt_head =3D item->firstseg; > - pkt_tail =3D pkt; > - } else { > - pkt_head =3D pkt; > - pkt_tail =3D item->firstseg; > - } > - > - /* check if the IPv4 packet length is greater than the max value = */ > - hdr_len =3D l2_offset + pkt_head->l2_len + pkt_head->l3_len + > - pkt_head->l4_len; > - l2_len =3D l2_offset > 0 ? pkt_head->outer_l2_len : pkt_head->l2_= len; > - if (unlikely(pkt_head->pkt_len - l2_len + pkt_tail->pkt_len - > - hdr_len > MAX_IPV4_PKT_LENGTH)) > - return 0; > - > - /* remove the packet header for the tail packet */ > - rte_pktmbuf_adj(pkt_tail, hdr_len); > - > - /* chain two packets together */ > - if (cmp > 0) { > - item->lastseg->next =3D pkt; > - item->lastseg =3D rte_pktmbuf_lastseg(pkt); > - /* update IP ID to the larger value */ > - item->ip_id =3D ip_id; > - } else { > - lastseg =3D rte_pktmbuf_lastseg(pkt); > - lastseg->next =3D item->firstseg; > - item->firstseg =3D pkt; > - /* update sent_seq to the smaller value */ > - item->sent_seq =3D sent_seq; > - item->ip_id =3D ip_id; > - } > - item->nb_merged++; > - > - /* update MBUF metadata for the merged packet */ > - pkt_head->nb_segs +=3D pkt_tail->nb_segs; > - pkt_head->pkt_len +=3D pkt_tail->pkt_len; > - > - return 1; > -} > - > -/* > - * Check if two TCP/IPv4 packets are neighbors. > - */ > -static inline int > -check_seq_option(struct gro_tcp4_item *item, > - struct rte_tcp_hdr *tcph, > - uint32_t sent_seq, > - uint16_t ip_id, > - uint16_t tcp_hl, > - uint16_t tcp_dl, > - uint16_t l2_offset, > - uint8_t is_atomic) > -{ > - struct rte_mbuf *pkt_orig =3D item->firstseg; > - struct rte_ipv4_hdr *iph_orig; > - struct rte_tcp_hdr *tcph_orig; > - uint16_t len, tcp_hl_orig; > - > - iph_orig =3D (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(pkt_orig, c= har > *) + > - l2_offset + pkt_orig->l2_len); > - tcph_orig =3D (struct rte_tcp_hdr *)((char *)iph_orig + > pkt_orig->l3_len); > - tcp_hl_orig =3D pkt_orig->l4_len; > - > - /* Check if TCP option fields equal */ > - len =3D RTE_MAX(tcp_hl, tcp_hl_orig) - sizeof(struct rte_tcp_hdr)= ; > - if ((tcp_hl !=3D tcp_hl_orig) || ((len > 0) && > - (memcmp(tcph + 1, tcph_orig + 1, > - len) !=3D 0))) > - return 0; > - > - /* Don't merge packets whose DF bits are different */ > - if (unlikely(item->is_atomic ^ is_atomic)) > - return 0; > - > - /* check if the two packets are neighbors */ > - len =3D pkt_orig->pkt_len - l2_offset - pkt_orig->l2_len - > - pkt_orig->l3_len - tcp_hl_orig; > - if ((sent_seq =3D=3D item->sent_seq + len) && (is_atomic || > - (ip_id =3D=3D item->ip_id + 1))) > - /* append the new packet */ > - return 1; > - else if ((sent_seq + tcp_dl =3D=3D item->sent_seq) && (is_atomic = || > - (ip_id + item->nb_merged =3D=3D item->ip_= id))) > - /* pre-pend the new packet */ > - return -1; > - > - return 0; > -} > #endif > diff --git a/lib/gro/gro_tcp6.c b/lib/gro/gro_tcp6.c > new file mode 100644 > index 0000000000..5aa39801e1 > --- /dev/null > +++ b/lib/gro/gro_tcp6.c > @@ -0,0 +1,268 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2023 Intel Corporation > + */ > + > +#include > +#include > +#include > + > +#include "gro_tcp6.h" > +#include "gro_tcp_internal.h" > + > +void * > +gro_tcp6_tbl_create(uint16_t socket_id, > + uint16_t max_flow_num, > + uint16_t max_item_per_flow) > +{ > + struct gro_tcp6_tbl *tbl; > + size_t size; > + uint32_t entries_num, i; > + > + entries_num =3D max_flow_num * max_item_per_flow; > + entries_num =3D RTE_MIN(entries_num, GRO_TCP6_TBL_MAX_ITEM_NUM); > + > + if (entries_num =3D=3D 0) > + return NULL; > + > + tbl =3D rte_zmalloc_socket(__func__, > + sizeof(struct gro_tcp6_tbl), > + RTE_CACHE_LINE_SIZE, > + socket_id); > + if (tbl =3D=3D NULL) > + return NULL; > + > + size =3D sizeof(struct gro_tcp_item) * entries_num; > + tbl->items =3D rte_zmalloc_socket(__func__, > + size, > + RTE_CACHE_LINE_SIZE, > + socket_id); > + if (tbl->items =3D=3D NULL) { > + rte_free(tbl); > + return NULL; > + } > + tbl->max_item_num =3D entries_num; > + > + size =3D sizeof(struct gro_tcp6_flow) * entries_num; > + tbl->flows =3D rte_zmalloc_socket(__func__, > + size, > + RTE_CACHE_LINE_SIZE, > + socket_id); > + if (tbl->flows =3D=3D NULL) { > + rte_free(tbl->items); > + rte_free(tbl); > + return NULL; > + } > + /* INVALID_ARRAY_INDEX indicates an empty flow */ > + for (i =3D 0; i < entries_num; i++) > + tbl->flows[i].start_index =3D INVALID_ARRAY_INDEX; > + tbl->max_flow_num =3D entries_num; > + > + return tbl; > +} > + > +void > +gro_tcp6_tbl_destroy(void *tbl) > +{ > + struct gro_tcp6_tbl *tcp_tbl =3D tbl; > + > + if (tcp_tbl) { > + rte_free(tcp_tbl->items); > + rte_free(tcp_tbl->flows); > + } > + rte_free(tcp_tbl); > +} > + > +static inline uint32_t > +find_an_empty_flow(struct gro_tcp6_tbl *tbl) > +{ > + uint32_t i; > + uint32_t max_flow_num =3D tbl->max_flow_num; > + > + for (i =3D 0; i < max_flow_num; i++) > + if (tbl->flows[i].start_index =3D=3D INVALID_ARRAY_INDEX) > + return i; > + return INVALID_ARRAY_INDEX; > +} > + > +static inline uint32_t > +insert_new_flow(struct gro_tcp6_tbl *tbl, > + struct tcp6_flow_key *src, > + uint32_t item_idx) > +{ > + struct tcp6_flow_key *dst; > + uint32_t flow_idx; > + > + flow_idx =3D find_an_empty_flow(tbl); > + if (unlikely(flow_idx =3D=3D INVALID_ARRAY_INDEX)) > + return INVALID_ARRAY_INDEX; > + > + dst =3D &(tbl->flows[flow_idx].key); > + > + ASSIGN_COMMON_TCP_KEY((&src->cmn_key), (&dst->cmn_key)); > + memcpy(&dst->src_addr[0], &src->src_addr[0], > sizeof(dst->src_addr)); > + memcpy(&dst->dst_addr[0], &src->dst_addr[0], > sizeof(dst->dst_addr)); > + dst->vtc_flow =3D src->vtc_flow; > + > + tbl->flows[flow_idx].start_index =3D item_idx; > + tbl->flow_num++; > + > + return flow_idx; > +} > + > +/* > + * update the packet length for the flushed packet. > + */ > +static inline void > +update_header(struct gro_tcp_item *item) > +{ > + struct rte_ipv6_hdr *ipv6_hdr; > + struct rte_mbuf *pkt =3D item->firstseg; > + > + ipv6_hdr =3D (struct rte_ipv6_hdr *)(rte_pktmbuf_mtod(pkt, char *= ) + > + pkt->l2_len); > + ipv6_hdr->payload_len =3D rte_cpu_to_be_16(pkt->pkt_len - > + pkt->l2_len - pkt->l3_len); > +} > + > +int32_t > +gro_tcp6_reassemble(struct rte_mbuf *pkt, > + struct gro_tcp6_tbl *tbl, > + uint64_t start_time) > +{ > + struct rte_ether_hdr *eth_hdr; > + struct rte_ipv6_hdr *ipv6_hdr; > + int32_t tcp_dl; > + uint16_t ip_tlen; > + struct tcp6_flow_key key; > + uint32_t i, max_flow_num, remaining_flow_num; > + uint32_t sent_seq; > + struct rte_tcp_hdr *tcp_hdr; > + uint8_t find; > + uint32_t item_idx; > + /* > + * Don't process the packet whose TCP header length is greater > + * than 60 bytes or less than 20 bytes. > + */ > + if (unlikely(INVALID_TCP_HDRLEN(pkt->l4_len))) > + return -1; > + > + eth_hdr =3D rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); > + ipv6_hdr =3D (struct rte_ipv6_hdr *)((char *)eth_hdr + pkt->l2_le= n); > + tcp_hdr =3D rte_pktmbuf_mtod_offset(pkt, struct rte_tcp_hdr *, > pkt->l2_len + pkt->l3_len); > + > + /* > + * Don't process the packet which has FIN, SYN, RST, PSH, URG, EC= E > + * or CWR set. > + */ > + if (tcp_hdr->tcp_flags !=3D RTE_TCP_ACK_FLAG) > + return -1; > + > + ip_tlen =3D rte_be_to_cpu_16(ipv6_hdr->payload_len); > + /* > + * Don't process the packet whose payload length is less than or > + * equal to 0. > + */ > + tcp_dl =3D ip_tlen - pkt->l4_len; > + if (tcp_dl <=3D 0) > + return -1; > + > + rte_ether_addr_copy(&(eth_hdr->src_addr), > &(key.cmn_key.eth_saddr)); > + rte_ether_addr_copy(&(eth_hdr->dst_addr), > &(key.cmn_key.eth_daddr)); > + memcpy(&key.src_addr[0], &ipv6_hdr->src_addr, > sizeof(key.src_addr)); > + memcpy(&key.dst_addr[0], &ipv6_hdr->dst_addr, > sizeof(key.dst_addr)); > + key.cmn_key.src_port =3D tcp_hdr->src_port; > + key.cmn_key.dst_port =3D tcp_hdr->dst_port; > + key.cmn_key.recv_ack =3D tcp_hdr->recv_ack; > + key.vtc_flow =3D ipv6_hdr->vtc_flow; > + > + /* Search for a matched flow. */ > + max_flow_num =3D tbl->max_flow_num; > + remaining_flow_num =3D tbl->flow_num; > + find =3D 0; > + for (i =3D 0; i < max_flow_num && remaining_flow_num; i++) { > + if (tbl->flows[i].start_index !=3D INVALID_ARRAY_INDEX) { > + if (is_same_tcp6_flow(&tbl->flows[i].key, &key)) = { > + find =3D 1; > + break; > + } > + remaining_flow_num--; > + } > + } > + > + if (find =3D=3D 0) { > + sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > + item_idx =3D insert_new_tcp_item(pkt, tbl->items, > &tbl->item_num, > + tbl->max_item_num, > start_time, > + INVALID_ARRAY_INDEX, > sent_seq, 0, true); > + if (item_idx =3D=3D INVALID_ARRAY_INDEX) > + return -1; > + if (insert_new_flow(tbl, &key, item_idx) =3D=3D > + INVALID_ARRAY_INDEX) { > + /* > + * Fail to insert a new flow, so delete the > + * stored packet. > + */ > + delete_tcp_item(tbl->items, item_idx, > &tbl->item_num, INVALID_ARRAY_INDEX); > + return -1; > + } > + return 0; > + } > + > + return process_tcp_item(pkt, tcp_hdr, tcp_dl, tbl->items, > tbl->flows[i].start_index, > + &tbl->item_num, > tbl->max_item_num, > + 0, true, start_time); > +} > + > +uint16_t > +gro_tcp6_tbl_timeout_flush(struct gro_tcp6_tbl *tbl, > + uint64_t flush_timestamp, > + struct rte_mbuf **out, > + uint16_t nb_out) > +{ > + uint16_t k =3D 0; > + uint32_t i, j; > + uint32_t max_flow_num =3D tbl->max_flow_num; > + > + for (i =3D 0; i < max_flow_num; i++) { > + if (unlikely(tbl->flow_num =3D=3D 0)) > + return k; > + > + j =3D tbl->flows[i].start_index; > + while (j !=3D INVALID_ARRAY_INDEX) { > + if (tbl->items[j].start_time <=3D flush_timestamp= ) { > + out[k++] =3D tbl->items[j].firstseg; > + if (tbl->items[j].nb_merged > 1) > + update_header(&(tbl->items[j])); > + /* > + * Delete the packet and get the next > + * packet in the flow. > + */ > + j =3D delete_tcp_item(tbl->items, j, > + &tbl->item_num, > INVALID_ARRAY_INDEX); > + tbl->flows[i].start_index =3D j; > + if (j =3D=3D INVALID_ARRAY_INDEX) > + tbl->flow_num--; > + > + if (unlikely(k =3D=3D nb_out)) > + return k; > + } else > + /* > + * The left packets in this flow won't be > + * timeout. Go to check other flows. > + */ > + break; > + } > + } > + return k; > +} > + > +uint32_t > +gro_tcp6_tbl_pkt_count(void *tbl) > +{ > + struct gro_tcp6_tbl *gro_tbl =3D tbl; > + > + if (gro_tbl) > + return gro_tbl->item_num; > + > + return 0; > +} > diff --git a/lib/gro/gro_tcp6.h b/lib/gro/gro_tcp6.h > new file mode 100644 > index 0000000000..073122f0ec > --- /dev/null > +++ b/lib/gro/gro_tcp6.h > @@ -0,0 +1,160 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2023 Intel Corporation > + */ > + > +#ifndef _GRO_TCP6_H_ > +#define _GRO_TCP6_H_ > + > +#include "gro_tcp.h" > + > +#define GRO_TCP6_TBL_MAX_ITEM_NUM (1024UL * 1024UL) > + > +/* Header fields representing a TCP/IPv6 flow */ > +struct tcp6_flow_key { > + struct cmn_tcp_key cmn_key; > + uint8_t src_addr[16]; > + uint8_t dst_addr[16]; > + rte_be32_t vtc_flow; > +}; > + > +struct gro_tcp6_flow { > + struct tcp6_flow_key key; > + /* > + * The index of the first packet in the flow. > + * INVALID_ARRAY_INDEX indicates an empty flow. > + */ > + uint32_t start_index; > +}; > + > +/* > + * TCP/IPv6 reassembly table structure. > + */ > +struct gro_tcp6_tbl { > + /* item array */ > + struct gro_tcp_item *items; > + /* flow array */ > + struct gro_tcp6_flow *flows; > + /* current item number */ > + uint32_t item_num; > + /* current flow num */ > + uint32_t flow_num; > + /* item array size */ > + uint32_t max_item_num; > + /* flow array size */ > + uint32_t max_flow_num; > +}; > + > +/** > + * This function creates a TCP/IPv6 reassembly table. > + * > + * @param socket_id > + * Socket index for allocating the TCP/IPv6 reassemble table > + * @param max_flow_num > + * The maximum number of flows in the TCP/IPv6 GRO table > + * @param max_item_per_flow > + * The maximum number of packets per flow > + * > + * @return > + * - Return the table pointer on success. > + * - Return NULL on failure. > + */ > +void *gro_tcp6_tbl_create(uint16_t socket_id, > + uint16_t max_flow_num, > + uint16_t max_item_per_flow); > + > +/** > + * This function destroys a TCP/IPv6 reassembly table. > + * > + * @param tbl > + * Pointer pointing to the TCP/IPv6 reassembly table. > + */ > +void gro_tcp6_tbl_destroy(void *tbl); > + > +/** > + * This function merges a TCP/IPv6 packet. It doesn't process the packet= , > + * which has SYN, FIN, RST, PSH, CWR, ECE or URG set, or doesn't have > + * payload. > + * > + * This function doesn't check if the packet has correct checksums and > + * doesn't re-calculate checksums for the merged packet. Additionally, > + * it assumes the packets are complete (i.e., MF=3D=3D0 && frag_off=3D= =3D0), > + * when IP fragmentation is possible (i.e., DF=3D=3D0). It returns the > + * packet, if the packet has invalid parameters (e.g. SYN bit is set) > + * or there is no available space in the table. > + * > + * @param pkt > + * Packet to reassemble > + * @param tbl > + * Pointer pointing to the TCP/IPv6 reassembly table > + * @start_time > + * The time when the packet is inserted into the table > + * > + * @return > + * - Return a positive value if the packet is merged. > + * - Return zero if the packet isn't merged but stored in the table. > + * - Return a negative value for invalid parameters or no available > + * space in the table. > + */ > +int32_t gro_tcp6_reassemble(struct rte_mbuf *pkt, > + struct gro_tcp6_tbl *tbl, > + uint64_t start_time); > + > +/** > + * This function flushes timeout packets in a TCP/IPv6 reassembly table, > + * and without updating checksums. > + * > + * @param tbl > + * TCP/IPv6 reassembly table pointer > + * @param flush_timestamp > + * Flush packets which are inserted into the table before or at the > + * flush_timestamp. > + * @param out > + * Pointer array used to keep flushed packets > + * @param nb_out > + * The element number in 'out'. It also determines the maximum number o= f > + * packets that can be flushed finally. > + * > + * @return > + * The number of flushed packets > + */ > +uint16_t gro_tcp6_tbl_timeout_flush(struct gro_tcp6_tbl *tbl, > + uint64_t flush_timestamp, > + struct rte_mbuf **out, > + uint16_t nb_out); > + > +/** > + * This function returns the number of the packets in a TCP/IPv6 > + * reassembly table. > + * > + * @param tbl > + * TCP/IPv6 reassembly table pointer > + * > + * @return > + * The number of packets in the table > + */ > +uint32_t gro_tcp6_tbl_pkt_count(void *tbl); > + > +/* > + * Check if two TCP/IPv6 packets belong to the same flow. > + */ > +static inline int > +is_same_tcp6_flow(struct tcp6_flow_key *k1, struct tcp6_flow_key *k2) > +{ > + rte_be32_t vtc_flow_diff; > + > + if (memcmp(&k1->src_addr, &k2->src_addr, 16)) > + return 0; > + if (memcmp(&k1->dst_addr, &k2->dst_addr, 16)) > + return 0; > + /* > + * IP version (4) Traffic Class (8) Flow Label (20) > + * All fields except Traffic class should be same > + */ > + vtc_flow_diff =3D (k1->vtc_flow ^ k2->vtc_flow); > + if (vtc_flow_diff & htonl(0xF00FFFFF)) > + return 0; > + > + return is_same_common_tcp_key(&k1->cmn_key, &k2->cmn_key); > +} > + > +#endif > diff --git a/lib/gro/gro_tcp_internal.h b/lib/gro/gro_tcp_internal.h > new file mode 100644 > index 0000000000..cc84abeaeb > --- /dev/null > +++ b/lib/gro/gro_tcp_internal.h > @@ -0,0 +1,128 @@ > + > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2023 Intel Corporation > + */ > + > +#ifndef _GRO_TCP_INTERNAL_H_ > +#define _GRO_TCP_INTERNAL_H_ > + > +static inline uint32_t > +find_an_empty_item(struct gro_tcp_item *items, > + uint32_t max_item_num) > +{ > + uint32_t i; > + > + for (i =3D 0; i < max_item_num; i++) > + if (items[i].firstseg =3D=3D NULL) > + return i; > + return INVALID_ARRAY_INDEX; > +} > + > +static inline uint32_t > +insert_new_tcp_item(struct rte_mbuf *pkt, > + struct gro_tcp_item *items, > + uint32_t *item_num, > + uint32_t max_item_num, > + uint64_t start_time, > + uint32_t prev_idx, > + uint32_t sent_seq, > + uint16_t ip_id, > + uint8_t is_atomic) > +{ > + uint32_t item_idx; > + > + item_idx =3D find_an_empty_item(items, max_item_num); > + if (item_idx =3D=3D INVALID_ARRAY_INDEX) > + return INVALID_ARRAY_INDEX; > + > + items[item_idx].firstseg =3D pkt; > + items[item_idx].lastseg =3D rte_pktmbuf_lastseg(pkt); > + items[item_idx].start_time =3D start_time; > + items[item_idx].next_pkt_idx =3D INVALID_ARRAY_INDEX; > + items[item_idx].sent_seq =3D sent_seq; > + items[item_idx].l3.ip_id =3D ip_id; > + items[item_idx].nb_merged =3D 1; > + items[item_idx].is_atomic =3D is_atomic; > + (*item_num) +=3D 1; > + > + /* if the previous packet exists, chain them together. */ > + if (prev_idx !=3D INVALID_ARRAY_INDEX) { > + items[item_idx].next_pkt_idx =3D > + items[prev_idx].next_pkt_idx; > + items[prev_idx].next_pkt_idx =3D item_idx; > + } > + > + return item_idx; > +} > + > +static inline uint32_t > +delete_tcp_item(struct gro_tcp_item *items, uint32_t item_idx, > + uint32_t *item_num, > + uint32_t prev_item_idx) > +{ > + uint32_t next_idx =3D items[item_idx].next_pkt_idx; > + > + /* NULL indicates an empty item */ > + items[item_idx].firstseg =3D NULL; > + (*item_num) -=3D 1; > + if (prev_item_idx !=3D INVALID_ARRAY_INDEX) > + items[prev_item_idx].next_pkt_idx =3D next_idx; > + > + return next_idx; > +} > + > +static inline int32_t > +process_tcp_item(struct rte_mbuf *pkt, > + struct rte_tcp_hdr *tcp_hdr, > + int32_t tcp_dl, > + struct gro_tcp_item *items, > + uint32_t item_idx, > + uint32_t *item_num, > + uint32_t max_item_num, > + uint16_t ip_id, > + uint8_t is_atomic, > + uint64_t start_time) > +{ > + uint32_t cur_idx; > + uint32_t prev_idx; > + int cmp; > + uint32_t sent_seq; > + > + sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > + /* > + * Check all packets in the flow and try to find a neighbor for > + * the input packet. > + */ > + cur_idx =3D item_idx; > + prev_idx =3D cur_idx; > + do { > + cmp =3D check_seq_option(&items[cur_idx], tcp_hdr, > + sent_seq, ip_id, pkt->l4_len, tcp_dl, 0, > + is_atomic); > + if (cmp) { > + if (merge_two_tcp_packets(&items[cur_idx], > + pkt, cmp, sent_seq, ip_id= , > 0)) > + return 1; > + /* > + * Fail to merge the two packets, as the packet > + * length is greater than the max value. Store > + * the packet into the flow. > + */ > + if (insert_new_tcp_item(pkt, items, item_num, > max_item_num, > + start_time, cur_idx, > sent_seq, ip_id, is_atomic) =3D=3D > + INVALID_ARRAY_INDEX) > + return -1; > + return 0; > + } > + prev_idx =3D cur_idx; > + cur_idx =3D items[cur_idx].next_pkt_idx; > + } while (cur_idx !=3D INVALID_ARRAY_INDEX); > + > + /* Fail to find a neighbor, so store the packet into the flow. */ > + if (insert_new_tcp_item(pkt, items, item_num, max_item_num, > start_time, prev_idx, sent_seq, > + ip_id, is_atomic) =3D=3D INVALID_ARRAY_IN= DEX) > + return -1; > + > + return 0; > +} > +#endif > diff --git a/lib/gro/gro_vxlan_tcp4.c b/lib/gro/gro_vxlan_tcp4.c > index 3be4deb7c7..6ab7001922 100644 > --- a/lib/gro/gro_vxlan_tcp4.c > +++ b/lib/gro/gro_vxlan_tcp4.c > @@ -116,7 +116,7 @@ insert_new_item(struct gro_vxlan_tcp4_tbl *tbl, > tbl->items[item_idx].inner_item.start_time =3D start_time; > tbl->items[item_idx].inner_item.next_pkt_idx =3D INVALID_ARRAY_IN= DEX; > tbl->items[item_idx].inner_item.sent_seq =3D sent_seq; > - tbl->items[item_idx].inner_item.ip_id =3D ip_id; > + tbl->items[item_idx].inner_item.l3.ip_id =3D ip_id; > tbl->items[item_idx].inner_item.nb_merged =3D 1; > tbl->items[item_idx].inner_item.is_atomic =3D is_atomic; > tbl->items[item_idx].outer_ip_id =3D outer_ip_id; > @@ -163,15 +163,9 @@ insert_new_flow(struct gro_vxlan_tcp4_tbl *tbl, > > dst =3D &(tbl->flows[flow_idx].key); > > - rte_ether_addr_copy(&(src->inner_key.eth_saddr), > - &(dst->inner_key.eth_saddr)); > - rte_ether_addr_copy(&(src->inner_key.eth_daddr), > - &(dst->inner_key.eth_daddr)); > + ASSIGN_COMMON_TCP_KEY((&(src->inner_key.cmn_key)), > (&(dst->inner_key.cmn_key))); > dst->inner_key.ip_src_addr =3D src->inner_key.ip_src_addr; > dst->inner_key.ip_dst_addr =3D src->inner_key.ip_dst_addr; > - dst->inner_key.recv_ack =3D src->inner_key.recv_ack; > - dst->inner_key.src_port =3D src->inner_key.src_port; > - dst->inner_key.dst_port =3D src->inner_key.dst_port; > > dst->vxlan_hdr.vx_flags =3D src->vxlan_hdr.vx_flags; > dst->vxlan_hdr.vx_vni =3D src->vxlan_hdr.vx_vni; > @@ -248,7 +242,7 @@ merge_two_vxlan_tcp4_packets(struct > gro_vxlan_tcp4_item *item, > uint16_t outer_ip_id, > uint16_t ip_id) > { > - if (merge_two_tcp4_packets(&item->inner_item, pkt, cmp, sent_seq, > + if (merge_two_tcp_packets(&item->inner_item, pkt, cmp, sent_seq, > ip_id, pkt->outer_l2_len + > pkt->outer_l3_len)) { > /* Update the outer IPv4 ID to the large value. */ > @@ -357,13 +351,13 @@ gro_vxlan_tcp4_reassemble(struct rte_mbuf *pkt, > > sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > > - rte_ether_addr_copy(&(eth_hdr->src_addr), > &(key.inner_key.eth_saddr)); > - rte_ether_addr_copy(&(eth_hdr->dst_addr), > &(key.inner_key.eth_daddr)); > + rte_ether_addr_copy(&(eth_hdr->src_addr), > &(key.inner_key.cmn_key.eth_saddr)); > + rte_ether_addr_copy(&(eth_hdr->dst_addr), > &(key.inner_key.cmn_key.eth_daddr)); > key.inner_key.ip_src_addr =3D ipv4_hdr->src_addr; > key.inner_key.ip_dst_addr =3D ipv4_hdr->dst_addr; > - key.inner_key.recv_ack =3D tcp_hdr->recv_ack; > - key.inner_key.src_port =3D tcp_hdr->src_port; > - key.inner_key.dst_port =3D tcp_hdr->dst_port; > + key.inner_key.cmn_key.recv_ack =3D tcp_hdr->recv_ack; > + key.inner_key.cmn_key.src_port =3D tcp_hdr->src_port; > + key.inner_key.cmn_key.dst_port =3D tcp_hdr->dst_port; > > key.vxlan_hdr.vx_flags =3D vxlan_hdr->vx_flags; > key.vxlan_hdr.vx_vni =3D vxlan_hdr->vx_vni; > diff --git a/lib/gro/gro_vxlan_tcp4.h b/lib/gro/gro_vxlan_tcp4.h > index 7832942a68..662db01a88 100644 > --- a/lib/gro/gro_vxlan_tcp4.h > +++ b/lib/gro/gro_vxlan_tcp4.h > @@ -36,7 +36,7 @@ struct gro_vxlan_tcp4_flow { > }; > > struct gro_vxlan_tcp4_item { > - struct gro_tcp4_item inner_item; > + struct gro_tcp_item inner_item; > /* IPv4 ID in the outer IPv4 header */ > uint16_t outer_ip_id; > /* Indicate if outer IPv4 ID can be ignored */ > diff --git a/lib/gro/meson.build b/lib/gro/meson.build > index e4fa2958bd..dbce05220d 100644 > --- a/lib/gro/meson.build > +++ b/lib/gro/meson.build > @@ -4,6 +4,7 @@ > sources =3D files( > 'rte_gro.c', > 'gro_tcp4.c', > + 'gro_tcp6.c', > 'gro_udp4.c', > 'gro_vxlan_tcp4.c', > 'gro_vxlan_udp4.c', > diff --git a/lib/gro/rte_gro.c b/lib/gro/rte_gro.c > index e35399fd42..d824eebd93 100644 > --- a/lib/gro/rte_gro.c > +++ b/lib/gro/rte_gro.c > @@ -8,6 +8,7 @@ > > #include "rte_gro.h" > #include "gro_tcp4.h" > +#include "gro_tcp6.h" > #include "gro_udp4.h" > #include "gro_vxlan_tcp4.h" > #include "gro_vxlan_udp4.h" > @@ -20,14 +21,16 @@ typedef uint32_t (*gro_tbl_pkt_count_fn)(void *tbl); > > static gro_tbl_create_fn tbl_create_fn[RTE_GRO_TYPE_MAX_NUM] =3D { > gro_tcp4_tbl_create, gro_vxlan_tcp4_tbl_create, > - gro_udp4_tbl_create, gro_vxlan_udp4_tbl_create, NULL}; > + gro_udp4_tbl_create, gro_vxlan_udp4_tbl_create, > gro_tcp6_tbl_create, NULL}; > static gro_tbl_destroy_fn tbl_destroy_fn[RTE_GRO_TYPE_MAX_NUM] =3D { > gro_tcp4_tbl_destroy, gro_vxlan_tcp4_tbl_destroy, > gro_udp4_tbl_destroy, gro_vxlan_udp4_tbl_destroy, > + gro_tcp6_tbl_destroy, > NULL}; > static gro_tbl_pkt_count_fn tbl_pkt_count_fn[RTE_GRO_TYPE_MAX_NUM] =3D { > gro_tcp4_tbl_pkt_count, > gro_vxlan_tcp4_tbl_pkt_count, > gro_udp4_tbl_pkt_count, > gro_vxlan_udp4_tbl_pkt_count, > + gro_tcp6_tbl_pkt_count, > NULL}; > > #define IS_IPV4_TCP_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \ > @@ -35,6 +38,12 @@ static gro_tbl_pkt_count_fn > tbl_pkt_count_fn[RTE_GRO_TYPE_MAX_NUM] =3D { > ((ptype & RTE_PTYPE_L4_FRAG) !=3D RTE_PTYPE_L4_FRAG) && \ > (RTE_ETH_IS_TUNNEL_PKT(ptype) =3D=3D 0)) > > +/* GRO with extension headers is not supported */ > +#define IS_IPV6_TCP_PKT(ptype) (RTE_ETH_IS_IPV6_HDR(ptype) && \ > + ((ptype & RTE_PTYPE_L4_TCP) =3D=3D RTE_PTYPE_L4_TCP) && \ > + ((ptype & RTE_PTYPE_L4_FRAG) !=3D RTE_PTYPE_L4_FRAG) && \ > + (RTE_ETH_IS_TUNNEL_PKT(ptype) =3D=3D 0)) > + > #define IS_IPV4_UDP_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \ > ((ptype & RTE_PTYPE_L4_UDP) =3D=3D RTE_PTYPE_L4_UDP) && \ > (RTE_ETH_IS_TUNNEL_PKT(ptype) =3D=3D 0)) > @@ -147,7 +156,11 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > /* allocate a reassembly table for TCP/IPv4 GRO */ > struct gro_tcp4_tbl tcp_tbl; > struct gro_tcp4_flow tcp_flows[RTE_GRO_MAX_BURST_ITEM_NUM]; > - struct gro_tcp4_item tcp_items[RTE_GRO_MAX_BURST_ITEM_NUM] =3D {{= 0} > }; > + struct gro_tcp_item tcp_items[RTE_GRO_MAX_BURST_ITEM_NUM] =3D {{0= } }; > + > + struct gro_tcp6_tbl tcp6_tbl; > + struct gro_tcp6_flow tcp6_flows[RTE_GRO_MAX_BURST_ITEM_NUM]; > + struct gro_tcp_item tcp6_items[RTE_GRO_MAX_BURST_ITEM_NUM] =3D {{= 0} > }; > > /* allocate a reassembly table for UDP/IPv4 GRO */ > struct gro_udp4_tbl udp_tbl; > @@ -171,10 +184,10 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > int32_t ret; > uint16_t i, unprocess_num =3D 0, nb_after_gro =3D nb_pkts; > uint8_t do_tcp4_gro =3D 0, do_vxlan_tcp_gro =3D 0, do_udp4_gro = =3D 0, > - do_vxlan_udp_gro =3D 0; > + do_vxlan_udp_gro =3D 0, do_tcp6_gro =3D 0; > > if (unlikely((param->gro_types & (RTE_GRO_IPV4_VXLAN_TCP_IPV4 | > - RTE_GRO_TCP_IPV4 | > + RTE_GRO_TCP_IPV4 | > RTE_GRO_TCP_IPV6 | > RTE_GRO_IPV4_VXLAN_UDP_IPV4 | > RTE_GRO_UDP_IPV4)) =3D=3D 0)) > return nb_pkts; > @@ -236,6 +249,18 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > do_udp4_gro =3D 1; > } > > + if (param->gro_types & RTE_GRO_TCP_IPV6) { > + for (i =3D 0; i < item_num; i++) > + tcp6_flows[i].start_index =3D INVALID_ARRAY_INDEX= ; > + > + tcp6_tbl.flows =3D tcp6_flows; > + tcp6_tbl.items =3D tcp6_items; > + tcp6_tbl.flow_num =3D 0; > + tcp6_tbl.item_num =3D 0; > + tcp6_tbl.max_flow_num =3D item_num; > + tcp6_tbl.max_item_num =3D item_num; > + do_tcp6_gro =3D 1; > + } > > for (i =3D 0; i < nb_pkts; i++) { > /* > @@ -276,6 +301,14 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > nb_after_gro--; > else if (ret < 0) > unprocess_pkts[unprocess_num++] =3D pkts[= i]; > + } else if (IS_IPV6_TCP_PKT(pkts[i]->packet_type) && > + do_tcp6_gro) { > + ret =3D gro_tcp6_reassemble(pkts[i], &tcp6_tbl, 0= ); > + if (ret > 0) > + /* merge successfully */ > + nb_after_gro--; > + else if (ret < 0) > + unprocess_pkts[unprocess_num++] =3D pkts[= i]; > } else > unprocess_pkts[unprocess_num++] =3D pkts[i]; > } > @@ -283,9 +316,17 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > if ((nb_after_gro < nb_pkts) > || (unprocess_num < nb_pkts)) { > i =3D 0; > + /* Copy unprocessed packets */ > + if (unprocess_num > 0) { > + memcpy(&pkts[i], unprocess_pkts, > + sizeof(struct rte_mbuf *) * > + unprocess_num); > + i =3D unprocess_num; > + } > + > /* Flush all packets from the tables */ > if (do_vxlan_tcp_gro) { > - i =3D > gro_vxlan_tcp4_tbl_timeout_flush(&vxlan_tcp_tbl, > + i +=3D > gro_vxlan_tcp4_tbl_timeout_flush(&vxlan_tcp_tbl, > 0, pkts, nb_pkts); > } > > @@ -304,13 +345,11 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > i +=3D gro_udp4_tbl_timeout_flush(&udp_tbl, 0, > &pkts[i], nb_pkts - i); > } > - /* Copy unprocessed packets */ > - if (unprocess_num > 0) { > - memcpy(&pkts[i], unprocess_pkts, > - sizeof(struct rte_mbuf *) * > - unprocess_num); > + > + if (do_tcp6_gro) { > + i +=3D gro_tcp6_tbl_timeout_flush(&tcp6_tbl, 0, > + &pkts[i], nb_pkts - i); > } > - nb_after_gro =3D i + unprocess_num; > } > > return nb_after_gro; > @@ -323,13 +362,13 @@ rte_gro_reassemble(struct rte_mbuf **pkts, > { > struct rte_mbuf *unprocess_pkts[nb_pkts]; > struct gro_ctx *gro_ctx =3D ctx; > - void *tcp_tbl, *udp_tbl, *vxlan_tcp_tbl, *vxlan_udp_tbl; > + void *tcp_tbl, *udp_tbl, *vxlan_tcp_tbl, *vxlan_udp_tbl, *tcp6_tb= l; > uint64_t current_time; > uint16_t i, unprocess_num =3D 0; > - uint8_t do_tcp4_gro, do_vxlan_tcp_gro, do_udp4_gro, > do_vxlan_udp_gro; > + uint8_t do_tcp4_gro, do_vxlan_tcp_gro, do_udp4_gro, > do_vxlan_udp_gro, do_tcp6_gro; > > if (unlikely((gro_ctx->gro_types & (RTE_GRO_IPV4_VXLAN_TCP_IPV4 | > - RTE_GRO_TCP_IPV4 | > + RTE_GRO_TCP_IPV4 | > RTE_GRO_TCP_IPV6 | > RTE_GRO_IPV4_VXLAN_UDP_IPV4 | > RTE_GRO_UDP_IPV4)) =3D=3D 0)) > return nb_pkts; > @@ -338,6 +377,7 @@ rte_gro_reassemble(struct rte_mbuf **pkts, > vxlan_tcp_tbl =3D gro_ctx->tbls[RTE_GRO_IPV4_VXLAN_TCP_IPV4_INDEX= ]; > udp_tbl =3D gro_ctx->tbls[RTE_GRO_UDP_IPV4_INDEX]; > vxlan_udp_tbl =3D gro_ctx->tbls[RTE_GRO_IPV4_VXLAN_UDP_IPV4_INDEX= ]; > + tcp6_tbl =3D gro_ctx->tbls[RTE_GRO_TCP_IPV6_INDEX]; > > do_tcp4_gro =3D (gro_ctx->gro_types & RTE_GRO_TCP_IPV4) =3D=3D > RTE_GRO_TCP_IPV4; > @@ -347,6 +387,7 @@ rte_gro_reassemble(struct rte_mbuf **pkts, > RTE_GRO_UDP_IPV4; > do_vxlan_udp_gro =3D (gro_ctx->gro_types & > RTE_GRO_IPV4_VXLAN_UDP_IPV4) =3D=3D > RTE_GRO_IPV4_VXLAN_UDP_IPV4; > + do_tcp6_gro =3D (gro_ctx->gro_types & RTE_GRO_TCP_IPV6) =3D=3D > RTE_GRO_TCP_IPV6; > > current_time =3D rte_rdtsc(); > > @@ -371,6 +412,11 @@ rte_gro_reassemble(struct rte_mbuf **pkts, > if (gro_udp4_reassemble(pkts[i], udp_tbl, > current_time) < 0) > unprocess_pkts[unprocess_num++] =3D pkts[= i]; > + } else if (IS_IPV6_TCP_PKT(pkts[i]->packet_type) && > + do_tcp6_gro) { > + if (gro_tcp6_reassemble(pkts[i], tcp6_tbl, > + current_time) < 0) > + unprocess_pkts[unprocess_num++] =3D pkts[= i]; > } else > unprocess_pkts[unprocess_num++] =3D pkts[i]; > } > @@ -426,6 +472,15 @@ rte_gro_timeout_flush(void *ctx, > gro_ctx->tbls[RTE_GRO_UDP_IPV4_INDEX], > flush_timestamp, > &out[num], left_nb_out); > + left_nb_out =3D max_nb_out - num; > + } > + > + if ((gro_types & RTE_GRO_TCP_IPV6) && left_nb_out > 0) { > + num +=3D gro_tcp6_tbl_timeout_flush( > + gro_ctx->tbls[RTE_GRO_TCP_IPV6_INDEX], > + flush_timestamp, > + &out[num], left_nb_out); > + > } > > return num; > diff --git a/lib/gro/rte_gro.h b/lib/gro/rte_gro.h > index 9f9ed4935a..c83dfd9ad1 100644 > --- a/lib/gro/rte_gro.h > +++ b/lib/gro/rte_gro.h > @@ -38,6 +38,9 @@ extern "C" { > #define RTE_GRO_IPV4_VXLAN_UDP_IPV4_INDEX 3 > #define RTE_GRO_IPV4_VXLAN_UDP_IPV4 (1ULL << > RTE_GRO_IPV4_VXLAN_UDP_IPV4_INDEX) > /**< VxLAN UDP/IPv4 GRO flag. */ > +#define RTE_GRO_TCP_IPV6_INDEX 4 > +#define RTE_GRO_TCP_IPV6 (1ULL << RTE_GRO_TCP_IPV6_INDEX) > +/**< TCP/IPv6 GRO flag. */ > > /** > * Structure used to create GRO context objects or used to pass > -- > 2.25.1 > >> Hi Jiyau, In the recent patch I have moved the functions that had the >> error in Windows to the header file and since that is used by gro_tcp6.c >> and gro_tcp4.c, I have moved it to gro_tcp_internal.h. There are other >> functions and ds reused by gro_vxlan_tcp4.c, I have moved them to gro_tc= p.h >> so that the functions that are not used by gro_vxlan_tcp4.c will not be >> included. >> > --00000000000097279c05fe2535f0 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 PGRpdiBkaXI9Imx0ciI+PGRpdiBkaXI9Imx0ciI+PGJyPjwvZGl2Pjxicj48ZGl2IGNsYXNzPSJn bWFpbF9xdW90ZSI+PGRpdiBkaXI9Imx0ciIgY2xhc3M9ImdtYWlsX2F0dHIiPk9uIFRodSwgSnVu IDE1LCAyMDIzIGF0IDExOjUw4oCvQU0gS3VtYXJhIFBhcmFtZXNod2FyYW4gJmx0OzxhIGhyZWY9 Im1haWx0bzprdW1hcmFwYXJhbWVzaDkyQGdtYWlsLmNvbSI+a3VtYXJhcGFyYW1lc2g5MkBnbWFp bC5jb208L2E+Jmd0OyB3cm90ZTo8YnI+PC9kaXY+PGJsb2NrcXVvdGUgY2xhc3M9ImdtYWlsX3F1 b3RlIiBzdHlsZT0ibWFyZ2luOjBweCAwcHggMHB4IDAuOGV4O2JvcmRlci1sZWZ0OjFweCBzb2xp ZCByZ2IoMjA0LDIwNCwyMDQpO3BhZGRpbmctbGVmdDoxZXgiPlRoZSBwYXRjaCBhZGRzIEdSTyBz dXBwb3J0IGZvciBUQ1AvaXB2NiBwYWNrZXRzLiBUaGlzIGRvZXMgbm90PGJyPg0KaW5jbHVkZSB0 aGUgc3VwcG9ydCBmb3IgdnhsYW4sIHVkcCBpcHY2IHBhY2tldHMuPGJyPg0KPGJyPg0KU2lnbmVk LW9mZi1ieTogS3VtYXJhIFBhcmFtZXNod2FyYW4gJmx0OzxhIGhyZWY9Im1haWx0bzprdW1hcmFw YXJhbWVzaDkyQGdtYWlsLmNvbSIgdGFyZ2V0PSJfYmxhbmsiPmt1bWFyYXBhcmFtZXNoOTJAZ21h aWwuY29tPC9hPiZndDs8YnI+DQotLS08YnI+DQp2MTo8YnI+DQrCoCDCoCDCoCDCoCAqIENoYW5n ZXMgdG8gc3VwcG9ydCBHUk8gZm9yIFRDUC9pcHY2IHBhY2tldHMuIFRoaXMgZG9lcyBub3QgaW5j bHVkZTxicj4NCsKgIMKgIMKgIMKgIMKgIHZ4bGFuIGNoYW5nZXMuIDxicj4NCsKgIMKgIMKgIMKg ICogVGhlIEdSTyBpcyBwZXJmb3JtZWQgb25seSBmb3IgaXB2NiBwYWNrZXRzIHRoYXQgZG9lcyBu b3QgY29udGFpbiA8YnI+DQrCoCDCoCDCoCDCoCDCoGV4dGVuc2lvbiBoZWFkZXJzLiA8YnI+DQrC oCDCoCDCoCDCoCAqIFRoZSBsb2dpYyBmb3IgdGhlIFRDUCBjb2FsZXNjaW5nIHJlbWFpbnMgdGhl IHNhbWUsIGluIGlwdjYgaGVhZGVyIDxicj4NCsKgIMKgIMKgIMKgIMKgIHRoZSBzb3VyY2UgYWRk cmVzcywgZGVzdGluYXRpb24gYWRkcmVzcywgZmxvdyBsYWJlbCwgdmVyc2lvbiBmaWVsZHMgPGJy Pg0KwqAgwqAgwqAgwqAgwqAgYXJlIGV4cGVjdGVkIHRvIGJlIHRoZSBzYW1lLiA8YnI+DQrCoCDC oCDCoCDCoCAqIFJlLW9yZ2FuaXNlZCB0aGUgY29kZSB0byByZXVzZSBjZXJ0YWluIHRjcCBmdW5j dGlvbnMgZm9yIGJvdGggaXB2NCBhbmQgPGJyPg0KwqAgwqAgwqAgwqAgwqAgaXB2NiBmbG93cy48 YnI+DQp2Mjo8YnI+DQrCoCDCoCDCoCDCoCAqIEZpeCBjb21tZW50cyBpbiBncm9fdGNwNi5oIGhl YWRlciBmaWxlLiA8YnI+DQo8YnI+DQp2Mzo8YnI+DQrCoCDCoCDCoCDCoCAqIEFkZGVyZXNzIHJl dmlldyBjb21tZW50cyB0byBmaXggY29kZSBkdXBsaWNhdGlvbiBmb3IgdjQgYW5kIHY2PGJyPg0K PGJyPg0KdjQ6PGJyPg0KwqAgwqAgwqAgwqAgKiBBZGRyZXNzZXMgcmV2aWV3IGNvbW1lbnRzIGZv ciB2MywgZG8gbm90IHVzZSBjYWxsYmFja3MgPGJyPg0KPGJyPg0KdjU6PGJyPg0KwqAgwqAgwqAg wqAgKiBBZGRyZXNzIHJldmlldyBjb21tZW50czxicj4NCjxicj4NCnY2Ojxicj4NCsKgIMKgIMKg IMKgICogRml4IHdhcm5pbmcgYW5kIGNvZGluZyBzdHlsZSBpc3N1ZXM8YnI+DQo8YnI+DQp2Nzo8 YnI+DQrCoCDCoCDCoCDCoCAqIEZpeCBidWlsZCBjb21waWxhdGlvbiBpc3N1ZTxicj4NCjxicj4N CnY4Ojxicj4NCsKgIMKgIMKgIMKgICogVXNlIGdyb190Y3BfaW50ZXJuYWwuaCBmb3IgZnVuY3Rp b25zIHVzZWQgZm9yIGdyb190Y3A0IGFuZCBncm9fdGNwNiBhbmQgdXNlPGJyPg0KwqAgwqAgwqAg wqAgwqAgZ3JvX3RjcC5oIGZvciBkYXRhIHN0cnVjdHVyZXMgYW5kIGZ1bmN0aW9ucyB1c2VkIGFj cm9zcyBncm9fdnhsYW5fdGNwNDxicj4NCjxicj4NCnY5Ojxicj4NCsKgIMKgIMKgIMKgICogUmVz b2x2ZSBtZXJnZSBjb25mbGljdCBhbmQgYWRkIGdyb190Y3AuaCBpbiBwcm9wZXIgcGF0aDxicj4N Cjxicj4NCsKgLi4uL2dlbmVyaWNfcmVjZWl2ZV9vZmZsb2FkX2xpYi5yc3TCoCDCoCDCoCDCoCDC oCDCoHzCoCAyMSArLTxicj4NCsKgZG9jL2d1aWRlcy9yZWxfbm90ZXMvcmVsZWFzZV8yM18wNy5y c3TCoCDCoCDCoCDCoCB8wqAgwqAyICs8YnI+DQrCoGxpYi9ncm8vZ3JvX3RjcC5owqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB8IDE4NyArKysrKysrKysrKys8YnI+ DQrCoGxpYi9ncm8vZ3JvX3RjcDQuY8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIHwgMTc3ICsrKy0tLS0tLS0tLTxicj4NCsKgbGliL2dyby9ncm9fdGNwNC5owqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfCAxNzAgKy0tLS0tLS0tLS08YnI+ DQrCoGxpYi9ncm8vZ3JvX3RjcDYuY8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIHwgMjY4ICsrKysrKysrKysrKysrKysrKzxicj4NCsKgbGliL2dyby9ncm9fdGNwNi5o wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfCAxNjAgKysrKysrKysr Kys8YnI+DQrCoGxpYi9ncm8vZ3JvX3RjcF9pbnRlcm5hbC5owqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgfCAxMjggKysrKysrKysrPGJyPg0KwqBsaWIvZ3JvL2dyb192eGxhbl90Y3A0LmPC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB8wqAgMjIgKy08YnI+DQrCoGxpYi9ncm8v Z3JvX3Z4bGFuX3RjcDQuaMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHzCoCDCoDIg Ky08YnI+DQrCoGxpYi9ncm8vbWVzb24uYnVpbGTCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHzCoCDCoDEgKzxicj4NCsKgbGliL2dyby9ydGVfZ3JvLmPCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHzCoCA4MyArKysrKy08YnI+DQrCoGxp Yi9ncm8vcnRlX2dyby5owqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqB8wqAgwqAzICs8YnI+DQrCoDEzIGZpbGVzIGNoYW5nZWQsIDg4MyBpbnNlcnRpb25zKCspLCAz NDEgZGVsZXRpb25zKC0pPGJyPg0KwqBjcmVhdGUgbW9kZSAxMDA2NDQgbGliL2dyby9ncm9fdGNw Lmg8YnI+DQrCoGNyZWF0ZSBtb2RlIDEwMDY0NCBsaWIvZ3JvL2dyb190Y3A2LmM8YnI+DQrCoGNy ZWF0ZSBtb2RlIDEwMDY0NCBsaWIvZ3JvL2dyb190Y3A2Lmg8YnI+DQrCoGNyZWF0ZSBtb2RlIDEw MDY0NCBsaWIvZ3JvL2dyb190Y3BfaW50ZXJuYWwuaDxicj4NCjxicj4NCmRpZmYgLS1naXQgYS9k b2MvZ3VpZGVzL3Byb2dfZ3VpZGUvZ2VuZXJpY19yZWNlaXZlX29mZmxvYWRfbGliLnJzdCBiL2Rv Yy9ndWlkZXMvcHJvZ19ndWlkZS9nZW5lcmljX3JlY2VpdmVfb2ZmbG9hZF9saWIucnN0PGJyPg0K aW5kZXggOThhNWQyOWJiYy4uNTMzY2RhN2Y1YyAxMDA2NDQ8YnI+DQotLS0gYS9kb2MvZ3VpZGVz L3Byb2dfZ3VpZGUvZ2VuZXJpY19yZWNlaXZlX29mZmxvYWRfbGliLnJzdDxicj4NCisrKyBiL2Rv Yy9ndWlkZXMvcHJvZ19ndWlkZS9nZW5lcmljX3JlY2VpdmVfb2ZmbG9hZF9saWIucnN0PGJyPg0K QEAgLTEzOCwyMCArMTM4LDIxIEBAIFRoZSBrZXktYmFzZWQgYWxnb3JpdGhtIGhhcyB0d28gY2hh cmFjdGVyczo8YnI+DQo8YnI+DQrCoCDCoCBLZXktYmFzZWQgUmVhc3NlbWJseSBBbGdvcml0aG08 YnI+DQo8YnI+DQotVENQL0lQdjQgR1JPPGJyPg0KLS0tLS0tLS0tLS0tLTxicj4NCitUQ1AtSVB2 NC9JUHY2IEdSTzxicj4NCistLS0tLS0tLS0tLS0tLS0tLTxicj4NCjxicj4NCi1UaGUgdGFibGUg c3RydWN0dXJlIHVzZWQgYnkgVENQL0lQdjQgR1JPIGNvbnRhaW5zIHR3byBhcnJheXM6IGZsb3cg YXJyYXk8YnI+DQorVGhlIHRhYmxlIHN0cnVjdHVyZSB1c2VkIGJ5IFRDUC1JUHY0L0lQdjYgR1JP IGNvbnRhaW5zIHR3byBhcnJheXM6IGZsb3cgYXJyYXk8YnI+DQrCoGFuZCBpdGVtIGFycmF5LiBU aGUgZmxvdyBhcnJheSBrZWVwcyBmbG93IGluZm9ybWF0aW9uLCBhbmQgdGhlIGl0ZW0gYXJyYXk8 YnI+DQota2VlcHMgcGFja2V0IGluZm9ybWF0aW9uLjxicj4NCitrZWVwcyBwYWNrZXQgaW5mb3Jt YXRpb24uIFRoZSBmbG93IGFycmF5IGlzIGRpZmZlcmVudCBmb3IgSVB2NCBhbmQgSVB2NiB3aGls ZTxicj4NCit0aGUgaXRlbSBhcnJheSBpcyB0aGUgc2FtZS48YnI+DQo8YnI+DQotSGVhZGVyIGZp ZWxkcyB1c2VkIHRvIGRlZmluZSBhIFRDUC9JUHY0IGZsb3cgaW5jbHVkZTo8YnI+DQorSGVhZGVy IGZpZWxkcyB1c2VkIHRvIGRlZmluZSBhIFRDUC1JUHY0L0lQdjYgZmxvdyBpbmNsdWRlOjxicj4N Cjxicj4NCi0tIHNvdXJjZSBhbmQgZGVzdGluYXRpb246IEV0aGVybmV0IGFuZCBJUCBhZGRyZXNz LCBUQ1AgcG9ydDxicj4NCistIGNvbW1vbiB0Y3Aga2V5IGZpZWxkcyA6IEV0aGVybmV0IGFkZHJl c3MsIFRDUCBwb3J0LCBUQ1AgYWNrbm93bGVkZ2UgbnVtYmVyPGJyPg0KKy0gdmVyc2lvbiBzcGVj aWZpYyBJUCBhZGRyZXNzPGJyPg0KKy0gSVB2NiBmbG93IGxhYmVsIGZvciBJUHY2IGZsb3c8YnI+ DQo8YnI+DQotLSBUQ1AgYWNrbm93bGVkZ2UgbnVtYmVyPGJyPg0KLTxicj4NCi1UQ1AvSVB2NCBw YWNrZXRzIHdob3NlIEZJTiwgU1lOLCBSU1QsIFVSRywgUFNILCBFQ0Ugb3IgQ1dSIGJpdCBpcyBz ZXQ8YnI+DQorVENQIHBhY2tldHMgd2hvc2UgRklOLCBTWU4sIFJTVCwgVVJHLCBQU0gsIEVDRSBv ciBDV1IgYml0IGlzIHNldDxicj4NCsKgd29uJiMzOTt0IGJlIHByb2Nlc3NlZC48YnI+DQo8YnI+ DQrCoEhlYWRlciBmaWVsZHMgZGVjaWRpbmcgaWYgdHdvIHBhY2tldHMgYXJlIG5laWdoYm9ycyBp bmNsdWRlOjxicj4NCkBAIC0xNTksNyArMTYwLDcgQEAgSGVhZGVyIGZpZWxkcyBkZWNpZGluZyBp ZiB0d28gcGFja2V0cyBhcmUgbmVpZ2hib3JzIGluY2x1ZGU6PGJyPg0KwqAtIFRDUCBzZXF1ZW5j ZSBudW1iZXI8YnI+DQo8YnI+DQrCoC0gSVB2NCBJRC4gVGhlIElQdjQgSUQgZmllbGRzIG9mIHRo ZSBwYWNrZXRzLCB3aG9zZSBERiBiaXQgaXMgMCwgc2hvdWxkPGJyPg0KLcKgIGJlIGluY3JlYXNl ZCBieSAxLjxicj4NCivCoCBiZSBpbmNyZWFzZWQgYnkgMS4gVGhpcyBpcyBhcHBsaWNhYmxlIG9u bHkgZm9yIElQdjQ8YnI+DQo8YnI+DQrCoFZ4TEFOIEdSTzxicj4NCsKgLS0tLS0tLS0tPGJyPg0K ZGlmZiAtLWdpdCBhL2RvYy9ndWlkZXMvcmVsX25vdGVzL3JlbGVhc2VfMjNfMDcucnN0IGIvZG9j L2d1aWRlcy9yZWxfbm90ZXMvcmVsZWFzZV8yM18wNy5yc3Q8YnI+DQppbmRleCAwMjdhZTdiZDJk Li43MTI0Y2Y0NWM3IDEwMDY0NDxicj4NCi0tLSBhL2RvYy9ndWlkZXMvcmVsX25vdGVzL3JlbGVh c2VfMjNfMDcucnN0PGJyPg0KKysrIGIvZG9jL2d1aWRlcy9yZWxfbm90ZXMvcmVsZWFzZV8yM18w Ny5yc3Q8YnI+DQpAQCAtMTcwLDYgKzE3MCw4IEBAIE5ldyBGZWF0dXJlczxicj4NCjxicj4NCsKg IMKgU2VlIDpkb2M6YC4uL3Byb2dfZ3VpZGUvcGRjcF9saWJgIGZvciBtb3JlIGluZm9ybWF0aW9u Ljxicj4NCjxicj4NCisqICoqQWRkZWQgc3VwcG9ydCBmb3IgVENQL0lQdjYgR1JPLioqPGJyPg0K K8KgICogRW5oYW5jZWQgdGhlIGV4aXN0aW5nIGxpYnJhcnkgdG8gc3VwcG9ydCBHUk8gZm9yIFRD UCBwYWNrZXRzIG92ZXIgSVB2NiBuZXR3b3JrLjxicj4NCjxicj4NCsKgUmVtb3ZlZCBJdGVtczxi cj4NCsKgLS0tLS0tLS0tLS0tLTxicj4NCmRpZmYgLS1naXQgYS9saWIvZ3JvL2dyb190Y3AuaCBi L2xpYi9ncm8vZ3JvX3RjcC5oPGJyPg0KbmV3IGZpbGUgbW9kZSAxMDA2NDQ8YnI+DQppbmRleCAw MDAwMDAwMDAwLi43YzdhNmEzMDA4PGJyPg0KLS0tIC9kZXYvbnVsbDxicj4NCisrKyBiL2xpYi9n cm8vZ3JvX3RjcC5oPGJyPg0KQEAgLTAsMCArMSwxODcgQEA8YnI+DQorLyogU1BEWC1MaWNlbnNl LUlkZW50aWZpZXI6IEJTRC0zLUNsYXVzZTxicj4NCisgKiBDb3B5cmlnaHQoYykgMjAyMyBJbnRl bCBDb3Jwb3JhdGlvbjxicj4NCisgKi88YnI+DQorI2lmbmRlZiBfR1JPX1RDUF9IXzxicj4NCisj ZGVmaW5lIF9HUk9fVENQX0hfPGJyPg0KKzxicj4NCisjZGVmaW5lIElOVkFMSURfQVJSQVlfSU5E RVggMHhmZmZmZmZmZlVMPGJyPg0KKzxicj4NCisjaW5jbHVkZSAmbHQ7cnRlX3RjcC5oJmd0Ozxi cj4NCis8YnI+DQorLyo8YnI+DQorICogVGhlIG1heCBsZW5ndGggb2YgYSBJUHY0IHBhY2tldCwg d2hpY2ggaW5jbHVkZXMgdGhlIGxlbmd0aCBvZiB0aGUgTDM8YnI+DQorICogaGVhZGVyLCB0aGUg TDQgaGVhZGVyIGFuZCB0aGUgZGF0YSBwYXlsb2FkLjxicj4NCisgKi88YnI+DQorI2RlZmluZSBN QVhfSVBfUEtUX0xFTkdUSCBVSU5UMTZfTUFYPGJyPg0KKzxicj4NCisvKiBUaGUgbWF4aW11bSBU Q1AgaGVhZGVyIGxlbmd0aCAqLzxicj4NCisjZGVmaW5lIE1BWF9UQ1BfSExFTiA2MDxicj4NCisj ZGVmaW5lIElOVkFMSURfVENQX0hEUkxFTihsZW4pIFw8YnI+DQorwqAgwqAgwqAgwqAoKChsZW4p ICZsdDsgc2l6ZW9mKHN0cnVjdCBydGVfdGNwX2hkcikpIHx8ICgobGVuKSAmZ3Q7IE1BWF9UQ1Bf SExFTikpPGJyPg0KKzxicj4NCitzdHJ1Y3QgY21uX3RjcF9rZXkgezxicj4NCivCoCDCoCDCoCDC oHN0cnVjdCBydGVfZXRoZXJfYWRkciBldGhfc2FkZHI7PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0 IHJ0ZV9ldGhlcl9hZGRyIGV0aF9kYWRkcjs8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCByZWN2 X2Fjazs8YnI+DQorwqAgwqAgwqAgwqB1aW50MTZfdCBzcmNfcG9ydDs8YnI+DQorwqAgwqAgwqAg wqB1aW50MTZfdCBkc3RfcG9ydDs8YnI+DQorfTs8YnI+DQorPGJyPg0KKyNkZWZpbmUgQVNTSUdO X0NPTU1PTl9UQ1BfS0VZKGsxLCBrMikgXDxicj4NCivCoCDCoCDCoCDCoGRvIHtcPGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJfY29weSgmYW1wOyhrMS0mZ3Q7ZXRo X3NhZGRyKSwgJmFtcDsoazItJmd0O2V0aF9zYWRkcikpOyBcPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJfY29weSgmYW1wOyhrMS0mZ3Q7ZXRoX2RhZGRyKSwgJmFt cDsoazItJmd0O2V0aF9kYWRkcikpOyBcPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgazIt Jmd0O3JlY3ZfYWNrID0gazEtJmd0O3JlY3ZfYWNrOyBcPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgazItJmd0O3NyY19wb3J0ID0gazEtJmd0O3NyY19wb3J0OyBcPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgazItJmd0O2RzdF9wb3J0ID0gazEtJmd0O2RzdF9wb3J0OyBcPGJyPg0K K8KgIMKgIMKgIMKgfSB3aGlsZSAoMCk8YnI+DQorPGJyPg0KK3N0cnVjdCBncm9fdGNwX2l0ZW0g ezxicj4NCivCoCDCoCDCoCDCoC8qPGJyPg0KK8KgIMKgIMKgIMKgICogVGhlIGZpcnN0IE1CVUYg c2VnbWVudCBvZiB0aGUgcGFja2V0LiBJZiB0aGUgdmFsdWU8YnI+DQorwqAgwqAgwqAgwqAgKiBp cyBOVUxMLCBpdCBtZWFucyB0aGUgaXRlbSBpcyBlbXB0eS48YnI+DQorwqAgwqAgwqAgwqAgKi88 YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX21idWYgKmZpcnN0c2VnOzxicj4NCivCoCDCoCDC oCDCoC8qIFRoZSBsYXN0IE1CVUYgc2VnbWVudCBvZiB0aGUgcGFja2V0ICovPGJyPg0KK8KgIMKg IMKgIMKgc3RydWN0IHJ0ZV9tYnVmICpsYXN0c2VnOzxicj4NCivCoCDCoCDCoCDCoC8qPGJyPg0K K8KgIMKgIMKgIMKgICogVGhlIHRpbWUgd2hlbiB0aGUgZmlyc3QgcGFja2V0IGlzIGluc2VydGVk IGludG8gdGhlIHRhYmxlLjxicj4NCivCoCDCoCDCoCDCoCAqIFRoaXMgdmFsdWUgd29uJiMzOTt0 IGJlIHVwZGF0ZWQsIGV2ZW4gaWYgdGhlIHBhY2tldCBpcyBtZXJnZWQ8YnI+DQorwqAgwqAgwqAg wqAgKiB3aXRoIG90aGVyIHBhY2tldHMuPGJyPg0KK8KgIMKgIMKgIMKgICovPGJyPg0KK8KgIMKg IMKgIMKgdWludDY0X3Qgc3RhcnRfdGltZTs8YnI+DQorwqAgwqAgwqAgwqAvKjxicj4NCivCoCDC oCDCoCDCoCAqIG5leHRfcGt0X2lkeCBpcyB1c2VkIHRvIGNoYWluIHRoZSBwYWNrZXRzIHRoYXQ8 YnI+DQorwqAgwqAgwqAgwqAgKiBhcmUgaW4gdGhlIHNhbWUgZmxvdyBidXQgY2FuJiMzOTt0IGJl IG1lcmdlZCB0b2dldGhlcjxicj4NCivCoCDCoCDCoCDCoCAqIChlLmcuIGNhdXNlZCBieSBwYWNr ZXQgcmVvcmRlcmluZykuPGJyPg0KK8KgIMKgIMKgIMKgICovPGJyPg0KK8KgIMKgIMKgIMKgdWlu dDMyX3QgbmV4dF9wa3RfaWR4Ozxicj4NCivCoCDCoCDCoCDCoC8qIFRDUCBzZXF1ZW5jZSBudW1i ZXIgb2YgdGhlIHBhY2tldCAqLzxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRfc2VxOzxi cj4NCivCoCDCoCDCoCDCoHVuaW9uIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiBJ UHY0IElEIG9mIHRoZSBwYWNrZXQgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50 MTZfdCBpcF9pZDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiBVbnVzZWQgZmllbGQg Zm9yIElQdjYgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCB1bnVzZWQ7 PGJyPg0KK8KgIMKgIMKgIMKgfSBsMzs8YnI+DQorwqAgwqAgwqAgwqAvKiB0aGUgbnVtYmVyIG9m IG1lcmdlZCBwYWNrZXRzICovPGJyPg0KK8KgIMKgIMKgIMKgdWludDE2X3QgbmJfbWVyZ2VkOzxi cj4NCivCoCDCoCDCoCDCoC8qIEluZGljYXRlIGlmIElQdjQgSUQgY2FuIGJlIGlnbm9yZWQgKi88 YnI+DQorwqAgwqAgwqAgwqB1aW50OF90IGlzX2F0b21pYzs8YnI+DQorfTs8YnI+DQorPGJyPg0K Ky8qPGJyPg0KKyAqIE1lcmdlIHR3byBUQ1AgcGFja2V0cyB3aXRob3V0IHVwZGF0aW5nIGNoZWNr c3Vtcy48YnI+DQorICogSWYgY21wIGlzIGxhcmdlciB0aGFuIDAsIGFwcGVuZCB0aGUgbmV3IHBh Y2tldCB0byB0aGU8YnI+DQorICogb3JpZ2luYWwgcGFja2V0LiBPdGhlcndpc2UsIHByZS1wZW5k IHRoZSBuZXcgcGFja2V0IHRvPGJyPg0KKyAqIHRoZSBvcmlnaW5hbCBwYWNrZXQuPGJyPg0KKyAq Lzxicj4NCitzdGF0aWMgaW5saW5lIGludDxicj4NCittZXJnZV90d29fdGNwX3BhY2tldHMoc3Ry dWN0IGdyb190Y3BfaXRlbSAqaXRlbSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzdHJ1 Y3QgcnRlX21idWYgKnBrdCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpbnQgY21wLDxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRfc2VxLDxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGlwX2lkLDxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoHVpbnQxNl90IGwyX29mZnNldCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHN0cnVj dCBydGVfbWJ1ZiAqcGt0X2hlYWQsICpwa3RfdGFpbCwgKmxhc3RzZWc7PGJyPg0KK8KgIMKgIMKg IMKgdWludDE2X3QgaGRyX2xlbiwgbDJfbGVuOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBpZiAo Y21wICZndDsgMCkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdF9oZWFkID0gaXRl bS0mZ3Q7Zmlyc3RzZWc7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcGt0X3RhaWwgPSBw a3Q7PGJyPg0KK8KgIMKgIMKgIMKgfSBlbHNlIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBwa3RfaGVhZCA9IHBrdDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3RfdGFpbCA9 IGl0ZW0tJmd0O2ZpcnN0c2VnOzxicj4NCivCoCDCoCDCoCDCoH08YnI+DQorPGJyPg0KK8KgIMKg IMKgIMKgLyogY2hlY2sgaWYgdGhlIElQdjQgcGFja2V0IGxlbmd0aCBpcyBncmVhdGVyIHRoYW4g dGhlIG1heCB2YWx1ZSAqLzxicj4NCivCoCDCoCDCoCDCoGhkcl9sZW4gPSBsMl9vZmZzZXQgKyBw a3RfaGVhZC0mZ3Q7bDJfbGVuICsgcGt0X2hlYWQtJmd0O2wzX2xlbiArPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgcGt0X2hlYWQtJmd0O2w0X2xlbjs8YnI+DQorwqAgwqAgwqAgwqBsMl9s ZW4gPSBsMl9vZmZzZXQgJmd0OyAwID8gcGt0X2hlYWQtJmd0O291dGVyX2wyX2xlbiA6IHBrdF9o ZWFkLSZndDtsMl9sZW47PGJyPg0KK8KgIMKgIMKgIMKgaWYgKHVubGlrZWx5KHBrdF9oZWFkLSZn dDtwa3RfbGVuIC0gbDJfbGVuICsgcGt0X3RhaWwtJmd0O3BrdF9sZW4gLTxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGhkcl9sZW4gJmd0OyBNQVhf SVBfUEtUX0xFTkdUSCkpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIDA7PGJy Pg0KKzxicj4NCivCoCDCoCDCoCDCoC8qIHJlbW92ZSB0aGUgcGFja2V0IGhlYWRlciBmb3IgdGhl IHRhaWwgcGFja2V0ICovPGJyPg0KK8KgIMKgIMKgIMKgcnRlX3BrdG1idWZfYWRqKHBrdF90YWls LCBoZHJfbGVuKTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgLyogY2hhaW4gdHdvIHBhY2tldHMg dG9nZXRoZXIgKi88YnI+DQorwqAgwqAgwqAgwqBpZiAoY21wICZndDsgMCkgezxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW0tJmd0O2xhc3RzZWctJmd0O25leHQgPSBwa3Q7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaXRlbS0mZ3Q7bGFzdHNlZyA9IHJ0ZV9wa3RtYnVmX2xh c3RzZWcocGt0KTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiB1cGRhdGUgSVAgSUQg dG8gdGhlIGxhcmdlciB2YWx1ZSAqLzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW0t Jmd0O2wzLmlwX2lkID0gaXBfaWQ7PGJyPg0KK8KgIMKgIMKgIMKgfSBlbHNlIHs8YnI+DQorwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqBsYXN0c2VnID0gcnRlX3BrdG1idWZfbGFzdHNlZyhwa3QpOzxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGxhc3RzZWctJmd0O25leHQgPSBpdGVtLSZndDtm aXJzdHNlZzs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpdGVtLSZndDtmaXJzdHNlZyA9 IHBrdDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiB1cGRhdGUgc2VudF9zZXEgdG8g dGhlIHNtYWxsZXIgdmFsdWUgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpdGVtLSZn dDtzZW50X3NlcSA9IHNlbnRfc2VxOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW0t Jmd0O2wzLmlwX2lkID0gaXBfaWQ7PGJyPg0KK8KgIMKgIMKgIMKgfTxicj4NCivCoCDCoCDCoCDC oGl0ZW0tJmd0O25iX21lcmdlZCsrOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAvKiB1cGRhdGUg TUJVRiBtZXRhZGF0YSBmb3IgdGhlIG1lcmdlZCBwYWNrZXQgKi88YnI+DQorwqAgwqAgwqAgwqBw a3RfaGVhZC0mZ3Q7bmJfc2VncyArPSBwa3RfdGFpbC0mZ3Q7bmJfc2Vnczs8YnI+DQorwqAgwqAg wqAgwqBwa3RfaGVhZC0mZ3Q7cGt0X2xlbiArPSBwa3RfdGFpbC0mZ3Q7cGt0X2xlbjs8YnI+DQor PGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIDE7PGJyPg0KK308YnI+DQorPGJyPg0KKy8qPGJyPg0K KyAqIENoZWNrIGlmIHR3byBUQ1AgcGFja2V0cyBhcmUgbmVpZ2hib3JzLjxicj4NCisgKi88YnI+ DQorc3RhdGljIGlubGluZSBpbnQ8YnI+DQorY2hlY2tfc2VxX29wdGlvbihzdHJ1Y3QgZ3JvX3Rj cF9pdGVtICppdGVtLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHN0cnVjdCBydGVfdGNw X2hkciAqdGNwaCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MzJfdCBzZW50X3Nl cSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCBpcF9pZCw8YnI+DQorwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCB0Y3BfaGwsPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgdWludDE2X3QgdGNwX2RsLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVp bnQxNl90IGwyX29mZnNldCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50OF90IGlz X2F0b21pYyk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBydGVfbWJ1ZiAqcGt0X29y aWcgPSBpdGVtLSZndDtmaXJzdHNlZzs8YnI+DQorwqAgwqAgwqAgwqBjaGFyICppcGhfb3JpZzs8 YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX3RjcF9oZHIgKnRjcGhfb3JpZzs8YnI+DQorwqAg wqAgwqAgwqB1aW50MTZfdCBsZW4sIHRjcF9obF9vcmlnOzxicj4NCis8YnI+DQorwqAgwqAgwqAg wqBpcGhfb3JpZyA9IChjaGFyICopKHJ0ZV9wa3RtYnVmX210b2QocGt0X29yaWcsIGNoYXIgKikg Kzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGwyX29mZnNldCArIHBr dF9vcmlnLSZndDtsMl9sZW4pOzxicj4NCivCoCDCoCDCoCDCoHRjcGhfb3JpZyA9IChzdHJ1Y3Qg cnRlX3RjcF9oZHIgKikoaXBoX29yaWcgKyBwa3Rfb3JpZy0mZ3Q7bDNfbGVuKTs8YnI+DQorwqAg wqAgwqAgwqB0Y3BfaGxfb3JpZyA9IHBrdF9vcmlnLSZndDtsNF9sZW47PGJyPg0KKzxicj4NCivC oCDCoCDCoCDCoC8qIENoZWNrIGlmIFRDUCBvcHRpb24gZmllbGRzIGVxdWFsICovPGJyPg0KK8Kg IMKgIMKgIMKgbGVuID0gUlRFX01BWCh0Y3BfaGwsIHRjcF9obF9vcmlnKSAtIHNpemVvZihzdHJ1 Y3QgcnRlX3RjcF9oZHIpOzxicj4NCivCoCDCoCDCoCDCoGlmICgodGNwX2hsICE9IHRjcF9obF9v cmlnKSB8fCAoKGxlbiAmZ3Q7IDApICZhbXA7JmFtcDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAobWVtY21wKHRjcGggKyAxLCB0Y3BoX29yaWcg KyAxLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoGxlbikgIT0gMCkpKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJl dHVybiAwOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAvKiBEb24mIzM5O3QgbWVyZ2UgcGFja2V0 cyB3aG9zZSBERiBiaXRzIGFyZSBkaWZmZXJlbnQgKi88YnI+DQorwqAgwqAgwqAgwqBpZiAodW5s aWtlbHkoaXRlbS0mZ3Q7aXNfYXRvbWljIF4gaXNfYXRvbWljKSk8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqByZXR1cm4gMDs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgLyogY2hlY2sgaWYg dGhlIHR3byBwYWNrZXRzIGFyZSBuZWlnaGJvcnMgKi88YnI+DQorwqAgwqAgwqAgwqBsZW4gPSBw a3Rfb3JpZy0mZ3Q7cGt0X2xlbiAtIGwyX29mZnNldCAtIHBrdF9vcmlnLSZndDtsMl9sZW4gLTxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdF9vcmlnLSZndDtsM19sZW4gLSB0Y3BfaGxf b3JpZzs8YnI+DQorwqAgwqAgwqAgwqBpZiAoKHNlbnRfc2VxID09IGl0ZW0tJmd0O3NlbnRfc2Vx ICsgbGVuKSAmYW1wOyZhbXA7IChpc19hdG9taWMgfHw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAoaXBfaWQgPT0gaXRlbS0mZ3Q7bDMuaXBfaWQg KyAxKSkpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyogYXBwZW5kIHRoZSBuZXcgcGFj a2V0ICovPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIDE7PGJyPg0KK8KgIMKg IMKgIMKgZWxzZSBpZiAoKHNlbnRfc2VxICsgdGNwX2RsID09IGl0ZW0tJmd0O3NlbnRfc2VxKSAm YW1wOyZhbXA7IChpc19hdG9taWMgfHw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAoaXBfaWQgKyBpdGVtLSZndDtuYl9tZXJnZWQgPT0gaXRlbS0m Z3Q7bDMuaXBfaWQpKSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiBwcmUtcGVuZCB0 aGUgbmV3IHBhY2tldCAqLzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiAtMTs8 YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIDA7PGJyPg0KK308YnI+DQorPGJyPg0KK3N0 YXRpYyBpbmxpbmUgaW50PGJyPg0KK2lzX3NhbWVfY29tbW9uX3RjcF9rZXkoc3RydWN0IGNtbl90 Y3Bfa2V5ICprMSwgc3RydWN0IGNtbl90Y3Bfa2V5ICprMik8YnI+DQorezxicj4NCivCoCDCoCDC oCDCoHJldHVybiAoIW1lbWNtcChrMSwgazIsIHNpemVvZihzdHJ1Y3QgY21uX3RjcF9rZXkpKSk7 PGJyPg0KK308YnI+DQorPGJyPg0KKyNlbmRpZjxicj4NCmRpZmYgLS1naXQgYS9saWIvZ3JvL2dy b190Y3A0LmMgYi9saWIvZ3JvL2dyb190Y3A0LmM8YnI+DQppbmRleCAwMDE0MDk2ZTYzLi42NjQ1 ZGU1OTJiIDEwMDY0NDxicj4NCi0tLSBhL2xpYi9ncm8vZ3JvX3RjcDQuYzxicj4NCisrKyBiL2xp Yi9ncm8vZ3JvX3RjcDQuYzxicj4NCkBAIC03LDYgKzcsNyBAQDxicj4NCsKgI2luY2x1ZGUgJmx0 O3J0ZV9ldGhkZXYuaCZndDs8YnI+DQo8YnI+DQrCoCNpbmNsdWRlICZxdW90O2dyb190Y3A0Lmgm cXVvdDs8YnI+DQorI2luY2x1ZGUgJnF1b3Q7Z3JvX3RjcF9pbnRlcm5hbC5oJnF1b3Q7PGJyPg0K PGJyPg0KwqB2b2lkICo8YnI+DQrCoGdyb190Y3A0X3RibF9jcmVhdGUodWludDE2X3Qgc29ja2V0 X2lkLDxicj4NCkBAIC0zMCw3ICszMSw3IEBAIGdyb190Y3A0X3RibF9jcmVhdGUodWludDE2X3Qg c29ja2V0X2lkLDxicj4NCsKgIMKgIMKgIMKgIGlmICh0YmwgPT0gTlVMTCk8YnI+DQrCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCByZXR1cm4gTlVMTDs8YnI+DQo8YnI+DQotwqAgwqAgwqAgwqBzaXpl ID0gc2l6ZW9mKHN0cnVjdCBncm9fdGNwNF9pdGVtKSAqIGVudHJpZXNfbnVtOzxicj4NCivCoCDC oCDCoCDCoHNpemUgPSBzaXplb2Yoc3RydWN0IGdyb190Y3BfaXRlbSkgKiBlbnRyaWVzX251bTs8 YnI+DQrCoCDCoCDCoCDCoCB0YmwtJmd0O2l0ZW1zID0gcnRlX3ptYWxsb2Nfc29ja2V0KF9fZnVu Y19fLDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNpemUsPGJyPg0K wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgUlRFX0NBQ0hFX0xJTkVfU0laRSw8 YnI+DQpAQCAtNzEsMTggKzcyLDYgQEAgZ3JvX3RjcDRfdGJsX2Rlc3Ryb3kodm9pZCAqdGJsKTxi cj4NCsKgIMKgIMKgIMKgIHJ0ZV9mcmVlKHRjcF90YmwpOzxicj4NCsKgfTxicj4NCjxicj4NCi1z dGF0aWMgaW5saW5lIHVpbnQzMl90PGJyPg0KLWZpbmRfYW5fZW1wdHlfaXRlbShzdHJ1Y3QgZ3Jv X3RjcDRfdGJsICp0YmwpPGJyPg0KLXs8YnI+DQotwqAgwqAgwqAgwqB1aW50MzJfdCBpOzxicj4N Ci3CoCDCoCDCoCDCoHVpbnQzMl90IG1heF9pdGVtX251bSA9IHRibC0mZ3Q7bWF4X2l0ZW1fbnVt Ozxicj4NCi08YnI+DQotwqAgwqAgwqAgwqBmb3IgKGkgPSAwOyBpICZsdDsgbWF4X2l0ZW1fbnVt OyBpKyspPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKHRibC0mZ3Q7aXRlbXNbaV0u Zmlyc3RzZWcgPT0gTlVMTCk8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqByZXR1cm4gaTs8YnI+DQotwqAgwqAgwqAgwqByZXR1cm4gSU5WQUxJRF9BUlJBWV9JTkRFWDs8 YnI+DQotfTxicj4NCi08YnI+DQrCoHN0YXRpYyBpbmxpbmUgdWludDMyX3Q8YnI+DQrCoGZpbmRf YW5fZW1wdHlfZmxvdyhzdHJ1Y3QgZ3JvX3RjcDRfdGJsICp0YmwpPGJyPg0KwqB7PGJyPg0KQEAg LTk1LDU2ICs4NCw2IEBAIGZpbmRfYW5fZW1wdHlfZmxvdyhzdHJ1Y3QgZ3JvX3RjcDRfdGJsICp0 YmwpPGJyPg0KwqAgwqAgwqAgwqAgcmV0dXJuIElOVkFMSURfQVJSQVlfSU5ERVg7PGJyPg0KwqB9 PGJyPg0KPGJyPg0KLXN0YXRpYyBpbmxpbmUgdWludDMyX3Q8YnI+DQotaW5zZXJ0X25ld19pdGVt KHN0cnVjdCBncm9fdGNwNF90YmwgKnRibCw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBz dHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50NjRf dCBzdGFydF90aW1lLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90IHByZXZf aWR4LDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRfc2VxLDxicj4N Ci3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGlwX2lkLDxicj4NCi3CoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHVpbnQ4X3QgaXNfYXRvbWljKTxicj4NCi17PGJyPg0KLcKgIMKgIMKgIMKg dWludDMyX3QgaXRlbV9pZHg7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoGl0ZW1faWR4ID0gZmlu ZF9hbl9lbXB0eV9pdGVtKHRibCk7PGJyPg0KLcKgIMKgIMKgIMKgaWYgKGl0ZW1faWR4ID09IElO VkFMSURfQVJSQVlfSU5ERVgpPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIElO VkFMSURfQVJSQVlfSU5ERVg7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbXNb aXRlbV9pZHhdLmZpcnN0c2VnID0gcGt0Ozxicj4NCi3CoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbXNb aXRlbV9pZHhdLmxhc3RzZWcgPSBydGVfcGt0bWJ1Zl9sYXN0c2VnKHBrdCk7PGJyPg0KLcKgIMKg IMKgIMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0uc3RhcnRfdGltZSA9IHN0YXJ0X3RpbWU7PGJy Pg0KLcKgIMKgIMKgIMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0ubmV4dF9wa3RfaWR4ID0gSU5W QUxJRF9BUlJBWV9JTkRFWDs8YnI+DQotwqAgwqAgwqAgwqB0YmwtJmd0O2l0ZW1zW2l0ZW1faWR4 XS5zZW50X3NlcSA9IHNlbnRfc2VxOzxicj4NCi3CoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbXNbaXRl bV9pZHhdLmlwX2lkID0gaXBfaWQ7PGJyPg0KLcKgIMKgIMKgIMKgdGJsLSZndDtpdGVtc1tpdGVt X2lkeF0ubmJfbWVyZ2VkID0gMTs8YnI+DQotwqAgwqAgwqAgwqB0YmwtJmd0O2l0ZW1zW2l0ZW1f aWR4XS5pc19hdG9taWMgPSBpc19hdG9taWM7PGJyPg0KLcKgIMKgIMKgIMKgdGJsLSZndDtpdGVt X251bSsrOzxicj4NCi08YnI+DQotwqAgwqAgwqAgwqAvKiBpZiB0aGUgcHJldmlvdXMgcGFja2V0 IGV4aXN0cywgY2hhaW4gdGhlbSB0b2dldGhlci4gKi88YnI+DQotwqAgwqAgwqAgwqBpZiAocHJl dl9pZHggIT0gSU5WQUxJRF9BUlJBWV9JTkRFWCkgezxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDC oCDCoHRibC0mZ3Q7aXRlbXNbaXRlbV9pZHhdLm5leHRfcGt0X2lkeCA9PGJyPg0KLcKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGJsLSZndDtpdGVtc1twcmV2X2lkeF0ubmV4dF9w a3RfaWR4Ozxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbXNbcHJldl9p ZHhdLm5leHRfcGt0X2lkeCA9IGl0ZW1faWR4Ozxicj4NCi3CoCDCoCDCoCDCoH08YnI+DQotPGJy Pg0KLcKgIMKgIMKgIMKgcmV0dXJuIGl0ZW1faWR4Ozxicj4NCi19PGJyPg0KLTxicj4NCi1zdGF0 aWMgaW5saW5lIHVpbnQzMl90PGJyPg0KLWRlbGV0ZV9pdGVtKHN0cnVjdCBncm9fdGNwNF90Ymwg KnRibCwgdWludDMyX3QgaXRlbV9pZHgsPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWlu dDMyX3QgcHJldl9pdGVtX2lkeCk8YnI+DQotezxicj4NCi3CoCDCoCDCoCDCoHVpbnQzMl90IG5l eHRfaWR4ID0gdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0ubmV4dF9wa3RfaWR4Ozxicj4NCi08YnI+ DQotwqAgwqAgwqAgwqAvKiBOVUxMIGluZGljYXRlcyBhbiBlbXB0eSBpdGVtICovPGJyPg0KLcKg IMKgIMKgIMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0uZmlyc3RzZWcgPSBOVUxMOzxicj4NCi3C oCDCoCDCoCDCoHRibC0mZ3Q7aXRlbV9udW0tLTs8YnI+DQotwqAgwqAgwqAgwqBpZiAocHJldl9p dGVtX2lkeCAhPSBJTlZBTElEX0FSUkFZX0lOREVYKTxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDC oCDCoHRibC0mZ3Q7aXRlbXNbcHJldl9pdGVtX2lkeF0ubmV4dF9wa3RfaWR4ID0gbmV4dF9pZHg7 PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoHJldHVybiBuZXh0X2lkeDs8YnI+DQotfTxicj4NCi08 YnI+DQrCoHN0YXRpYyBpbmxpbmUgdWludDMyX3Q8YnI+DQrCoGluc2VydF9uZXdfZmxvdyhzdHJ1 Y3QgZ3JvX3RjcDRfdGJsICp0YmwsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3RydWN0 IHRjcDRfZmxvd19rZXkgKnNyYyw8YnI+DQpAQCAtMTU5LDEzICs5OCwxMCBAQCBpbnNlcnRfbmV3 X2Zsb3coc3RydWN0IGdyb190Y3A0X3RibCAqdGJsLDxicj4NCjxicj4NCsKgIMKgIMKgIMKgIGRz dCA9ICZhbXA7KHRibC0mZ3Q7Zmxvd3NbZmxvd19pZHhdLmtleSk7PGJyPg0KPGJyPg0KLcKgIMKg IMKgIMKgcnRlX2V0aGVyX2FkZHJfY29weSgmYW1wOyhzcmMtJmd0O2V0aF9zYWRkciksICZhbXA7 KGRzdC0mZ3Q7ZXRoX3NhZGRyKSk7PGJyPg0KLcKgIMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJfY29w eSgmYW1wOyhzcmMtJmd0O2V0aF9kYWRkciksICZhbXA7KGRzdC0mZ3Q7ZXRoX2RhZGRyKSk7PGJy Pg0KK8KgIMKgIMKgIMKgQVNTSUdOX0NPTU1PTl9UQ1BfS0VZKCgmYW1wO3NyYy0mZ3Q7Y21uX2tl eSksICgmYW1wO2RzdC0mZ3Q7Y21uX2tleSkpOzxicj4NCis8YnI+DQrCoCDCoCDCoCDCoCBkc3Qt Jmd0O2lwX3NyY19hZGRyID0gc3JjLSZndDtpcF9zcmNfYWRkcjs8YnI+DQrCoCDCoCDCoCDCoCBk c3QtJmd0O2lwX2RzdF9hZGRyID0gc3JjLSZndDtpcF9kc3RfYWRkcjs8YnI+DQotwqAgwqAgwqAg wqBkc3QtJmd0O3JlY3ZfYWNrID0gc3JjLSZndDtyZWN2X2Fjazs8YnI+DQotwqAgwqAgwqAgwqBk c3QtJmd0O3NyY19wb3J0ID0gc3JjLSZndDtzcmNfcG9ydDs8YnI+DQotwqAgwqAgwqAgwqBkc3Qt Jmd0O2RzdF9wb3J0ID0gc3JjLSZndDtkc3RfcG9ydDs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCB0 YmwtJmd0O2Zsb3dzW2Zsb3dfaWR4XS5zdGFydF9pbmRleCA9IGl0ZW1faWR4Ozxicj4NCsKgIMKg IMKgIMKgIHRibC0mZ3Q7Zmxvd19udW0rKzs8YnI+DQpAQCAtMTczLDIxICsxMDksNiBAQCBpbnNl cnRfbmV3X2Zsb3coc3RydWN0IGdyb190Y3A0X3RibCAqdGJsLDxicj4NCsKgIMKgIMKgIMKgIHJl dHVybiBmbG93X2lkeDs8YnI+DQrCoH08YnI+DQo8YnI+DQotLyo8YnI+DQotICogdXBkYXRlIHRo ZSBwYWNrZXQgbGVuZ3RoIGZvciB0aGUgZmx1c2hlZCBwYWNrZXQuPGJyPg0KLSAqLzxicj4NCi1z dGF0aWMgaW5saW5lIHZvaWQ8YnI+DQotdXBkYXRlX2hlYWRlcihzdHJ1Y3QgZ3JvX3RjcDRfaXRl bSAqaXRlbSk8YnI+DQotezxicj4NCi3CoCDCoCDCoCDCoHN0cnVjdCBydGVfaXB2NF9oZHIgKmlw djRfaGRyOzxicj4NCi3CoCDCoCDCoCDCoHN0cnVjdCBydGVfbWJ1ZiAqcGt0ID0gaXRlbS0mZ3Q7 Zmlyc3RzZWc7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoGlwdjRfaGRyID0gKHN0cnVjdCBydGVf aXB2NF9oZHIgKikocnRlX3BrdG1idWZfbXRvZChwa3QsIGNoYXIgKikgKzxicj4NCi3CoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdC0mZ3Q7bDJfbGVuKTs8YnI+DQotwqAgwqAg wqAgwqBpcHY0X2hkci0mZ3Q7dG90YWxfbGVuZ3RoID0gcnRlX2NwdV90b19iZV8xNihwa3QtJmd0 O3BrdF9sZW4gLTxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdC0m Z3Q7bDJfbGVuKTs8YnI+DQotfTxicj4NCi08YnI+DQrCoGludDMyX3Q8YnI+DQrCoGdyb190Y3A0 X3JlYXNzZW1ibGUoc3RydWN0IHJ0ZV9tYnVmICpwa3QsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgc3RydWN0IGdyb190Y3A0X3RibCAqdGJsLDxicj4NCkBAIC0yMDIsOSArMTIzLDggQEAg Z3JvX3RjcDRfcmVhc3NlbWJsZShzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQrCoCDCoCDCoCDC oCB1aW50OF90IGlzX2F0b21pYzs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCBzdHJ1Y3QgdGNwNF9m bG93X2tleSBrZXk7PGJyPg0KLcKgIMKgIMKgIMKgdWludDMyX3QgY3VyX2lkeCwgcHJldl9pZHgs IGl0ZW1faWR4Ozxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IGl0ZW1faWR4Ozxicj4NCsKgIMKg IMKgIMKgIHVpbnQzMl90IGksIG1heF9mbG93X251bSwgcmVtYWluaW5nX2Zsb3dfbnVtOzxicj4N Ci3CoCDCoCDCoCDCoGludCBjbXA7PGJyPg0KwqAgwqAgwqAgwqAgdWludDhfdCBmaW5kOzxicj4N Cjxicj4NCsKgIMKgIMKgIMKgIC8qPGJyPg0KQEAgLTIzOSw2ICsxNTksMTQgQEAgZ3JvX3RjcDRf cmVhc3NlbWJsZShzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQrCoCDCoCDCoCDCoCBpZiAodGNw X2RsICZsdDs9IDApPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuIC0xOzxicj4N Cjxicj4NCivCoCDCoCDCoCDCoHJ0ZV9ldGhlcl9hZGRyX2NvcHkoJmFtcDsoZXRoX2hkci0mZ3Q7 c3JjX2FkZHIpLCAmYW1wOyhrZXkuY21uX2tleS5ldGhfc2FkZHIpKTs8YnI+DQorwqAgwqAgwqAg wqBydGVfZXRoZXJfYWRkcl9jb3B5KCZhbXA7KGV0aF9oZHItJmd0O2RzdF9hZGRyKSwgJmFtcDso a2V5LmNtbl9rZXkuZXRoX2RhZGRyKSk7PGJyPg0KK8KgIMKgIMKgIMKga2V5LmlwX3NyY19hZGRy ID0gaXB2NF9oZHItJmd0O3NyY19hZGRyOzxicj4NCivCoCDCoCDCoCDCoGtleS5pcF9kc3RfYWRk ciA9IGlwdjRfaGRyLSZndDtkc3RfYWRkcjs8YnI+DQorwqAgwqAgwqAgwqBrZXkuY21uX2tleS5z cmNfcG9ydCA9IHRjcF9oZHItJmd0O3NyY19wb3J0Ozxicj4NCivCoCDCoCDCoCDCoGtleS5jbW5f a2V5LmRzdF9wb3J0ID0gdGNwX2hkci0mZ3Q7ZHN0X3BvcnQ7PGJyPg0KK8KgIMKgIMKgIMKga2V5 LmNtbl9rZXkucmVjdl9hY2sgPSB0Y3BfaGRyLSZndDtyZWN2X2Fjazs8YnI+DQorPGJyPg0KwqAg wqAgwqAgwqAgLyo8YnI+DQrCoCDCoCDCoCDCoCDCoCogU2F2ZSBJUHY0IElEIGZvciB0aGUgcGFj a2V0IHdob3NlIERGIGJpdCBpcyAwLiBGb3IgdGhlIHBhY2tldDxicj4NCsKgIMKgIMKgIMKgIMKg KiB3aG9zZSBERiBiaXQgaXMgMSwgSVB2NCBJRCBpcyBpZ25vcmVkLjxicj4NCkBAIC0yNDYsMTUg KzE3NCw2IEBAIGdyb190Y3A0X3JlYXNzZW1ibGUoc3RydWN0IHJ0ZV9tYnVmICpwa3QsPGJyPg0K wqAgwqAgwqAgwqAgZnJhZ19vZmYgPSBydGVfYmVfdG9fY3B1XzE2KGlwdjRfaGRyLSZndDtmcmFn bWVudF9vZmZzZXQpOzxicj4NCsKgIMKgIMKgIMKgIGlzX2F0b21pYyA9IChmcmFnX29mZiAmYW1w OyBSVEVfSVBWNF9IRFJfREZfRkxBRykgPT0gUlRFX0lQVjRfSERSX0RGX0ZMQUc7PGJyPg0KwqAg wqAgwqAgwqAgaXBfaWQgPSBpc19hdG9taWMgPyAwIDogcnRlX2JlX3RvX2NwdV8xNihpcHY0X2hk ci0mZ3Q7cGFja2V0X2lkKTs8YnI+DQotwqAgwqAgwqAgwqBzZW50X3NlcSA9IHJ0ZV9iZV90b19j cHVfMzIodGNwX2hkci0mZ3Q7c2VudF9zZXEpOzxicj4NCi08YnI+DQotwqAgwqAgwqAgwqBydGVf ZXRoZXJfYWRkcl9jb3B5KCZhbXA7KGV0aF9oZHItJmd0O3NyY19hZGRyKSwgJmFtcDsoa2V5LmV0 aF9zYWRkcikpOzxicj4NCi3CoCDCoCDCoCDCoHJ0ZV9ldGhlcl9hZGRyX2NvcHkoJmFtcDsoZXRo X2hkci0mZ3Q7ZHN0X2FkZHIpLCAmYW1wOyhrZXkuZXRoX2RhZGRyKSk7PGJyPg0KLcKgIMKgIMKg IMKga2V5LmlwX3NyY19hZGRyID0gaXB2NF9oZHItJmd0O3NyY19hZGRyOzxicj4NCi3CoCDCoCDC oCDCoGtleS5pcF9kc3RfYWRkciA9IGlwdjRfaGRyLSZndDtkc3RfYWRkcjs8YnI+DQotwqAgwqAg wqAgwqBrZXkuc3JjX3BvcnQgPSB0Y3BfaGRyLSZndDtzcmNfcG9ydDs8YnI+DQotwqAgwqAgwqAg wqBrZXkuZHN0X3BvcnQgPSB0Y3BfaGRyLSZndDtkc3RfcG9ydDs8YnI+DQotwqAgwqAgwqAgwqBr ZXkucmVjdl9hY2sgPSB0Y3BfaGRyLSZndDtyZWN2X2Fjazs8YnI+DQo8YnI+DQrCoCDCoCDCoCDC oCAvKiBTZWFyY2ggZm9yIGEgbWF0Y2hlZCBmbG93LiAqLzxicj4NCsKgIMKgIMKgIMKgIG1heF9m bG93X251bSA9IHRibC0mZ3Q7bWF4X2Zsb3dfbnVtOzxicj4NCkBAIC0yNzAsNjMgKzE4OSw0NCBA QCBncm9fdGNwNF9yZWFzc2VtYmxlKHN0cnVjdCBydGVfbWJ1ZiAqcGt0LDxicj4NCsKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIH08YnI+DQrCoCDCoCDCoCDCoCB9PGJyPg0KPGJyPg0KLcKgIMKgIMKg IMKgLyo8YnI+DQotwqAgwqAgwqAgwqAgKiBGYWlsIHRvIGZpbmQgYSBtYXRjaGVkIGZsb3cuIElu c2VydCBhIG5ldyBmbG93IGFuZCBzdG9yZSB0aGU8YnI+DQotwqAgwqAgwqAgwqAgKiBwYWNrZXQg aW50byB0aGUgZmxvdy48YnI+DQotwqAgwqAgwqAgwqAgKi88YnI+DQrCoCDCoCDCoCDCoCBpZiAo ZmluZCA9PSAwKSB7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaXRlbV9pZHggPSBpbnNl cnRfbmV3X2l0ZW0odGJsLCBwa3QsIHN0YXJ0X3RpbWUsPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgSU5WQUxJRF9BUlJBWV9JTkRFWCwgc2VudF9z ZXEsIGlwX2lkLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoGlzX2F0b21pYyk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc2VudF9zZXEg PSBydGVfYmVfdG9fY3B1XzMyKHRjcF9oZHItJmd0O3NlbnRfc2VxKTs8YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqBpdGVtX2lkeCA9IGluc2VydF9uZXdfdGNwX2l0ZW0ocGt0LCB0YmwtJmd0 O2l0ZW1zLCAmYW1wO3RibC0mZ3Q7aXRlbV9udW0sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGJsLSZn dDttYXhfaXRlbV9udW0sIHN0YXJ0X3RpbWUsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgSU5WQUxJRF9B UlJBWV9JTkRFWCwgc2VudF9zZXEsIGlwX2lkLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlzX2F0b21p Yyk7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKGl0ZW1faWR4ID09IElOVkFMSURf QVJSQVlfSU5ERVgpPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0 dXJuIC0xOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChpbnNlcnRfbmV3X2Zsb3co dGJsLCAmYW1wO2tleSwgaXRlbV9pZHgpID09PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgSU5WQUxJRF9BUlJBWV9JTkRFWCkgezxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoElOVkFMSURfQVJSQVlfSU5ERVgpIHs8YnI+ DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAvKjxicj4NCsKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgKiBGYWlsIHRvIGluc2VydCBhIG5ldyBmbG93LCBz byBkZWxldGUgdGhlPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAq IHN0b3JlZCBwYWNrZXQuPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg ICovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZGVsZXRlX2l0ZW0o dGJsLCBpdGVtX2lkeCwgSU5WQUxJRF9BUlJBWV9JTkRFWCk7PGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBkZWxldGVfdGNwX2l0ZW0odGJsLSZndDtpdGVtcywgaXRlbV9pZHgsICZhbXA7dGJs LSZndDtpdGVtX251bSwgSU5WQUxJRF9BUlJBWV9JTkRFWCk7PGJyPg0KwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuIC0xOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIH08YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXR1cm4gMDs8YnI+DQrCoCDCoCDC oCDCoCB9PGJyPg0KPGJyPg0KLcKgIMKgIMKgIMKgLyo8YnI+DQotwqAgwqAgwqAgwqAgKiBDaGVj ayBhbGwgcGFja2V0cyBpbiB0aGUgZmxvdyBhbmQgdHJ5IHRvIGZpbmQgYSBuZWlnaGJvciBmb3I8 YnI+DQotwqAgwqAgwqAgwqAgKiB0aGUgaW5wdXQgcGFja2V0Ljxicj4NCi3CoCDCoCDCoCDCoCAq Lzxicj4NCi3CoCDCoCDCoCDCoGN1cl9pZHggPSB0YmwtJmd0O2Zsb3dzW2ldLnN0YXJ0X2luZGV4 Ozxicj4NCi3CoCDCoCDCoCDCoHByZXZfaWR4ID0gY3VyX2lkeDs8YnI+DQotwqAgwqAgwqAgwqBk byB7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgY21wID0gY2hlY2tfc2VxX29wdGlvbigm YW1wOyh0YmwtJmd0O2l0ZW1zW2N1cl9pZHhdKSwgdGNwX2hkciw8YnI+DQotwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzZW50X3NlcSwgaXBfaWQsIHBrdC0m Z3Q7bDRfbGVuLCB0Y3BfZGwsIDAsPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgaXNfYXRvbWljKTs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBpZiAoY21wKSB7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYg KG1lcmdlX3R3b190Y3A0X3BhY2tldHMoJmFtcDsodGJsLSZndDtpdGVtc1tjdXJfaWR4XSksPGJy Pg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgcGt0LCBjbXAsIHNlbnRfc2VxLCBpcF9pZCwgMCkpPGJyPg0KLcKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIDE7PGJy Pg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyo8YnI+DQotwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKiBGYWlsIHRvIG1lcmdlIHRoZSB0d28gcGFja2V0 cywgYXMgdGhlIHBhY2tldDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCAqIGxlbmd0aCBpcyBncmVhdGVyIHRoYW4gdGhlIG1heCB2YWx1ZS4gU3RvcmU8YnI+DQotwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKiB0aGUgcGFja2V0IGludG8gdGhlIGZs b3cuPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICovPGJyPg0KLcKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGluc2VydF9uZXdfaXRlbSh0Ymws IHBrdCwgc3RhcnRfdGltZSwgY3VyX2lkeCw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzZW50X3NlcSwg aXBfaWQsIGlzX2F0b21pYykgPT08YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBJTlZBTElEX0FSUkFZX0lOREVYKTxicj4NCi3C oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiAtMTs8 YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gMDs8YnI+DQot wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcHJl dl9pZHggPSBjdXJfaWR4Ozxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGN1cl9pZHggPSB0 YmwtJmd0O2l0ZW1zW2N1cl9pZHhdLm5leHRfcGt0X2lkeDs8YnI+DQotwqAgwqAgwqAgwqB9IHdo aWxlIChjdXJfaWR4ICE9IElOVkFMSURfQVJSQVlfSU5ERVgpOzxicj4NCivCoCDCoCDCoCDCoHJl dHVybiBwcm9jZXNzX3RjcF9pdGVtKHBrdCwgdGNwX2hkciwgdGNwX2RsLCB0YmwtJmd0O2l0ZW1z LCB0YmwtJmd0O2Zsb3dzW2ldLnN0YXJ0X2luZGV4LDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCZhbXA7 dGJsLSZndDtpdGVtX251bSwgdGJsLSZndDttYXhfaXRlbV9udW0sPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgaXBfaWQsIGlzX2F0b21pYywgc3RhcnRfdGltZSk7PGJyPg0KK308YnI+DQo8YnI+DQotwqAg wqAgwqAgwqAvKiBGYWlsIHRvIGZpbmQgYSBuZWlnaGJvciwgc28gc3RvcmUgdGhlIHBhY2tldCBp bnRvIHRoZSBmbG93LiAqLzxicj4NCi3CoCDCoCDCoCDCoGlmIChpbnNlcnRfbmV3X2l0ZW0odGJs LCBwa3QsIHN0YXJ0X3RpbWUsIHByZXZfaWR4LCBzZW50X3NlcSw8YnI+DQotwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpcF9pZCwgaXNfYXRvbWljKSA9PSBJ TlZBTElEX0FSUkFZX0lOREVYKTxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiAt MTs8YnI+DQorLyo8YnI+DQorICogdXBkYXRlIHRoZSBwYWNrZXQgbGVuZ3RoIGZvciB0aGUgZmx1 c2hlZCBwYWNrZXQuPGJyPg0KKyAqLzxicj4NCitzdGF0aWMgaW5saW5lIHZvaWQ8YnI+DQordXBk YXRlX2hlYWRlcihzdHJ1Y3QgZ3JvX3RjcF9pdGVtICppdGVtKTxicj4NCit7PGJyPg0KK8KgIMKg IMKgIMKgc3RydWN0IHJ0ZV9pcHY0X2hkciAqaXB2NF9oZHI7PGJyPg0KK8KgIMKgIMKgIMKgc3Ry dWN0IHJ0ZV9tYnVmICpwa3QgPSBpdGVtLSZndDtmaXJzdHNlZzs8YnI+DQo8YnI+DQotwqAgwqAg wqAgwqByZXR1cm4gMDs8YnI+DQorwqAgwqAgwqAgwqBpcHY0X2hkciA9IChzdHJ1Y3QgcnRlX2lw djRfaGRyICopKHJ0ZV9wa3RtYnVmX210b2QocGt0LCBjaGFyICopICs8YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3QtJmd0O2wyX2xlbik7PGJyPg0KK8KgIMKgIMKg IMKgaXB2NF9oZHItJmd0O3RvdGFsX2xlbmd0aCA9IHJ0ZV9jcHVfdG9fYmVfMTYocGt0LSZndDtw a3RfbGVuIC08YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3QtJmd0 O2wyX2xlbik7PGJyPg0KwqB9PGJyPg0KPGJyPg0KwqB1aW50MTZfdDxicj4NCkBAIC0zNTMsNyAr MjUzLDggQEAgZ3JvX3RjcDRfdGJsX3RpbWVvdXRfZmx1c2goc3RydWN0IGdyb190Y3A0X3RibCAq dGJsLDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgKiBEZWxldGUgdGhlIHBhY2tldCBhbmQgZ2V0IHRoZSBuZXh0PGJyPg0KwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAqIHBhY2tldCBpbiB0aGUgZmxv dy48YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg aiA9IGRlbGV0ZV9pdGVtKHRibCwgaiwgSU5WQUxJRF9BUlJBWV9JTkRFWCk7PGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaiA9IGRlbGV0ZV90Y3Bf aXRlbSh0YmwtJmd0O2l0ZW1zLCBqLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCZh bXA7dGJsLSZndDtpdGVtX251bSwgSU5WQUxJRF9BUlJBWV9JTkRFWCk7PGJyPg0KwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdGJsLSZndDtmbG93c1tpXS5z dGFydF9pbmRleCA9IGo7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgaWYgKGogPT0gSU5WQUxJRF9BUlJBWV9JTkRFWCk8YnI+DQrCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB0YmwtJmd0 O2Zsb3dfbnVtLS07PGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vZ3JvX3RjcDQuaCBiL2xpYi9n cm8vZ3JvX3RjcDQuaDxicj4NCmluZGV4IDIxMmY5N2EwNDIuLjI0NWU1ZGE0ODYgMTAwNjQ0PGJy Pg0KLS0tIGEvbGliL2dyby9ncm9fdGNwNC5oPGJyPg0KKysrIGIvbGliL2dyby9ncm9fdGNwNC5o PGJyPg0KQEAgLTUsMzIgKzUsMTUgQEA8YnI+DQrCoCNpZm5kZWYgX0dST19UQ1A0X0hfPGJyPg0K wqAjZGVmaW5lIF9HUk9fVENQNF9IXzxicj4NCjxicj4NCi0jaW5jbHVkZSAmbHQ7cnRlX3RjcC5o Jmd0Ozxicj4NCisjaW5jbHVkZSAmcXVvdDtncm9fdGNwLmgmcXVvdDs8YnI+DQo8YnI+DQotI2Rl ZmluZSBJTlZBTElEX0FSUkFZX0lOREVYIDB4ZmZmZmZmZmZVTDxicj4NCsKgI2RlZmluZSBHUk9f VENQNF9UQkxfTUFYX0lURU1fTlVNICgxMDI0VUwgKiAxMDI0VUwpPGJyPg0KPGJyPg0KLS8qPGJy Pg0KLSAqIFRoZSBtYXggbGVuZ3RoIG9mIGEgSVB2NCBwYWNrZXQsIHdoaWNoIGluY2x1ZGVzIHRo ZSBsZW5ndGggb2YgdGhlIEwzPGJyPg0KLSAqIGhlYWRlciwgdGhlIEw0IGhlYWRlciBhbmQgdGhl IGRhdGEgcGF5bG9hZC48YnI+DQotICovPGJyPg0KLSNkZWZpbmUgTUFYX0lQVjRfUEtUX0xFTkdU SCBVSU5UMTZfTUFYPGJyPg0KLTxicj4NCi0vKiBUaGUgbWF4aW11bSBUQ1AgaGVhZGVyIGxlbmd0 aCAqLzxicj4NCi0jZGVmaW5lIE1BWF9UQ1BfSExFTiA2MDxicj4NCi0jZGVmaW5lIElOVkFMSURf VENQX0hEUkxFTihsZW4pIFw8YnI+DQotwqAgwqAgwqAgwqAoKChsZW4pICZsdDsgc2l6ZW9mKHN0 cnVjdCBydGVfdGNwX2hkcikpIHx8ICgobGVuKSAmZ3Q7IE1BWF9UQ1BfSExFTikpPGJyPg0KLTxi cj4NCi0vKiBIZWFkZXIgZmllbGRzIHJlcHJlc2VudGluZyBhIFRDUC9JUHY0IGZsb3cgKi88YnI+ DQorLyogSGVhZGVyIGZpZWxkcyByZXByZXNlbnRpbmcgY29tbW9uIGZpZWxkcyBpbiBUQ1AgZmxv dyAqLzxicj4NCsKgc3RydWN0IHRjcDRfZmxvd19rZXkgezxicj4NCi3CoCDCoCDCoCDCoHN0cnVj dCBydGVfZXRoZXJfYWRkciBldGhfc2FkZHI7PGJyPg0KLcKgIMKgIMKgIMKgc3RydWN0IHJ0ZV9l dGhlcl9hZGRyIGV0aF9kYWRkcjs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgY21uX3RjcF9rZXkg Y21uX2tleTs8YnI+DQrCoCDCoCDCoCDCoCB1aW50MzJfdCBpcF9zcmNfYWRkcjs8YnI+DQrCoCDC oCDCoCDCoCB1aW50MzJfdCBpcF9kc3RfYWRkcjs8YnI+DQotPGJyPg0KLcKgIMKgIMKgIMKgdWlu dDMyX3QgcmVjdl9hY2s7PGJyPg0KLcKgIMKgIMKgIMKgdWludDE2X3Qgc3JjX3BvcnQ7PGJyPg0K LcKgIMKgIMKgIMKgdWludDE2X3QgZHN0X3BvcnQ7PGJyPg0KwqB9Ozxicj4NCjxicj4NCsKgc3Ry dWN0IGdyb190Y3A0X2Zsb3cgezxicj4NCkBAIC00Miw0MiArMjUsMTIgQEAgc3RydWN0IGdyb190 Y3A0X2Zsb3cgezxicj4NCsKgIMKgIMKgIMKgIHVpbnQzMl90IHN0YXJ0X2luZGV4Ozxicj4NCsKg fTs8YnI+DQo8YnI+DQotc3RydWN0IGdyb190Y3A0X2l0ZW0gezxicj4NCi3CoCDCoCDCoCDCoC8q PGJyPg0KLcKgIMKgIMKgIMKgICogVGhlIGZpcnN0IE1CVUYgc2VnbWVudCBvZiB0aGUgcGFja2V0 LiBJZiB0aGUgdmFsdWU8YnI+DQotwqAgwqAgwqAgwqAgKiBpcyBOVUxMLCBpdCBtZWFucyB0aGUg aXRlbSBpcyBlbXB0eS48YnI+DQotwqAgwqAgwqAgwqAgKi88YnI+DQotwqAgwqAgwqAgwqBzdHJ1 Y3QgcnRlX21idWYgKmZpcnN0c2VnOzxicj4NCi3CoCDCoCDCoCDCoC8qIFRoZSBsYXN0IE1CVUYg c2VnbWVudCBvZiB0aGUgcGFja2V0ICovPGJyPg0KLcKgIMKgIMKgIMKgc3RydWN0IHJ0ZV9tYnVm ICpsYXN0c2VnOzxicj4NCi3CoCDCoCDCoCDCoC8qPGJyPg0KLcKgIMKgIMKgIMKgICogVGhlIHRp bWUgd2hlbiB0aGUgZmlyc3QgcGFja2V0IGlzIGluc2VydGVkIGludG8gdGhlIHRhYmxlLjxicj4N Ci3CoCDCoCDCoCDCoCAqIFRoaXMgdmFsdWUgd29uJiMzOTt0IGJlIHVwZGF0ZWQsIGV2ZW4gaWYg dGhlIHBhY2tldCBpcyBtZXJnZWQ8YnI+DQotwqAgwqAgwqAgwqAgKiB3aXRoIG90aGVyIHBhY2tl dHMuPGJyPg0KLcKgIMKgIMKgIMKgICovPGJyPg0KLcKgIMKgIMKgIMKgdWludDY0X3Qgc3RhcnRf dGltZTs8YnI+DQotwqAgwqAgwqAgwqAvKjxicj4NCi3CoCDCoCDCoCDCoCAqIG5leHRfcGt0X2lk eCBpcyB1c2VkIHRvIGNoYWluIHRoZSBwYWNrZXRzIHRoYXQ8YnI+DQotwqAgwqAgwqAgwqAgKiBh cmUgaW4gdGhlIHNhbWUgZmxvdyBidXQgY2FuJiMzOTt0IGJlIG1lcmdlZCB0b2dldGhlcjxicj4N Ci3CoCDCoCDCoCDCoCAqIChlLmcuIGNhdXNlZCBieSBwYWNrZXQgcmVvcmRlcmluZykuPGJyPg0K LcKgIMKgIMKgIMKgICovPGJyPg0KLcKgIMKgIMKgIMKgdWludDMyX3QgbmV4dF9wa3RfaWR4Ozxi cj4NCi3CoCDCoCDCoCDCoC8qIFRDUCBzZXF1ZW5jZSBudW1iZXIgb2YgdGhlIHBhY2tldCAqLzxi cj4NCi3CoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRfc2VxOzxicj4NCi3CoCDCoCDCoCDCoC8qIElQ djQgSUQgb2YgdGhlIHBhY2tldCAqLzxicj4NCi3CoCDCoCDCoCDCoHVpbnQxNl90IGlwX2lkOzxi cj4NCi3CoCDCoCDCoCDCoC8qIHRoZSBudW1iZXIgb2YgbWVyZ2VkIHBhY2tldHMgKi88YnI+DQot wqAgwqAgwqAgwqB1aW50MTZfdCBuYl9tZXJnZWQ7PGJyPg0KLcKgIMKgIMKgIMKgLyogSW5kaWNh dGUgaWYgSVB2NCBJRCBjYW4gYmUgaWdub3JlZCAqLzxicj4NCi3CoCDCoCDCoCDCoHVpbnQ4X3Qg aXNfYXRvbWljOzxicj4NCi19Ozxicj4NCi08YnI+DQrCoC8qPGJyPg0KwqAgKiBUQ1AvSVB2NCBy ZWFzc2VtYmx5IHRhYmxlIHN0cnVjdHVyZS48YnI+DQrCoCAqLzxicj4NCsKgc3RydWN0IGdyb190 Y3A0X3RibCB7PGJyPg0KwqAgwqAgwqAgwqAgLyogaXRlbSBhcnJheSAqLzxicj4NCi3CoCDCoCDC oCDCoHN0cnVjdCBncm9fdGNwNF9pdGVtICppdGVtczs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3Qg Z3JvX3RjcF9pdGVtICppdGVtczs8YnI+DQrCoCDCoCDCoCDCoCAvKiBmbG93IGFycmF5ICovPGJy Pg0KwqAgwqAgwqAgwqAgc3RydWN0IGdyb190Y3A0X2Zsb3cgKmZsb3dzOzxicj4NCsKgIMKgIMKg IMKgIC8qIGN1cnJlbnQgaXRlbSBudW1iZXIgKi88YnI+DQpAQCAtMTg2LDEyMCArMTM5LDkgQEAg dWludDMyX3QgZ3JvX3RjcDRfdGJsX3BrdF9jb3VudCh2b2lkICp0YmwpOzxicj4NCsKgc3RhdGlj IGlubGluZSBpbnQ8YnI+DQrCoGlzX3NhbWVfdGNwNF9mbG93KHN0cnVjdCB0Y3A0X2Zsb3dfa2V5 IGsxLCBzdHJ1Y3QgdGNwNF9mbG93X2tleSBrMik8YnI+DQrCoHs8YnI+DQotwqAgwqAgwqAgwqBy ZXR1cm4gKHJ0ZV9pc19zYW1lX2V0aGVyX2FkZHIoJmFtcDtrMS5ldGhfc2FkZHIsICZhbXA7azIu ZXRoX3NhZGRyKSAmYW1wOyZhbXA7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgcnRlX2lzX3NhbWVfZXRoZXJfYWRkcigmYW1wO2sxLmV0aF9kYWRkciwgJmFtcDtrMi5l dGhfZGFkZHIpICZhbXA7JmFtcDs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAoazEuaXBfc3JjX2FkZHIgPT0gazIuaXBfc3JjX2FkZHIpICZhbXA7JmFtcDs8YnI+DQor wqAgwqAgwqAgwqByZXR1cm4gKChrMS5pcF9zcmNfYWRkciA9PSBrMi5pcF9zcmNfYWRkcikgJmFt cDsmYW1wOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIChrMS5pcF9k c3RfYWRkciA9PSBrMi5pcF9kc3RfYWRkcikgJmFtcDsmYW1wOzxicj4NCi3CoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoChrMS5yZWN2X2FjayA9PSBrMi5yZWN2X2FjaykgJmFtcDsm YW1wOzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoChrMS5zcmNfcG9y dCA9PSBrMi5zcmNfcG9ydCkgJmFtcDsmYW1wOzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoChrMS5kc3RfcG9ydCA9PSBrMi5kc3RfcG9ydCkpOzxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlzX3NhbWVfY29tbW9uX3RjcF9rZXkoJmFtcDtr MS5jbW5fa2V5LCAmYW1wO2syLmNtbl9rZXkpKTs8YnI+DQrCoH08YnI+DQo8YnI+DQotLyo8YnI+ DQotICogTWVyZ2UgdHdvIFRDUC9JUHY0IHBhY2tldHMgd2l0aG91dCB1cGRhdGluZyBjaGVja3N1 bXMuPGJyPg0KLSAqIElmIGNtcCBpcyBsYXJnZXIgdGhhbiAwLCBhcHBlbmQgdGhlIG5ldyBwYWNr ZXQgdG8gdGhlPGJyPg0KLSAqIG9yaWdpbmFsIHBhY2tldC4gT3RoZXJ3aXNlLCBwcmUtcGVuZCB0 aGUgbmV3IHBhY2tldCB0bzxicj4NCi0gKiB0aGUgb3JpZ2luYWwgcGFja2V0Ljxicj4NCi0gKi88 YnI+DQotc3RhdGljIGlubGluZSBpbnQ8YnI+DQotbWVyZ2VfdHdvX3RjcDRfcGFja2V0cyhzdHJ1 Y3QgZ3JvX3RjcDRfaXRlbSAqaXRlbSw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzdHJ1 Y3QgcnRlX21idWYgKnBrdCw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpbnQgY21wLDxi cj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRfc2VxLDxicj4NCi3CoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGlwX2lkLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDC oCDCoCDCoHVpbnQxNl90IGwyX29mZnNldCk8YnI+DQotezxicj4NCi3CoCDCoCDCoCDCoHN0cnVj dCBydGVfbWJ1ZiAqcGt0X2hlYWQsICpwa3RfdGFpbCwgKmxhc3RzZWc7PGJyPg0KLcKgIMKgIMKg IMKgdWludDE2X3QgaGRyX2xlbiwgbDJfbGVuOzxicj4NCi08YnI+DQotwqAgwqAgwqAgwqBpZiAo Y21wICZndDsgMCkgezxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdF9oZWFkID0gaXRl bS0mZ3Q7Zmlyc3RzZWc7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcGt0X3RhaWwgPSBw a3Q7PGJyPg0KLcKgIMKgIMKgIMKgfSBlbHNlIHs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBwa3RfaGVhZCA9IHBrdDs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3RfdGFpbCA9 IGl0ZW0tJmd0O2ZpcnN0c2VnOzxicj4NCi3CoCDCoCDCoCDCoH08YnI+DQotPGJyPg0KLcKgIMKg IMKgIMKgLyogY2hlY2sgaWYgdGhlIElQdjQgcGFja2V0IGxlbmd0aCBpcyBncmVhdGVyIHRoYW4g dGhlIG1heCB2YWx1ZSAqLzxicj4NCi3CoCDCoCDCoCDCoGhkcl9sZW4gPSBsMl9vZmZzZXQgKyBw a3RfaGVhZC0mZ3Q7bDJfbGVuICsgcGt0X2hlYWQtJmd0O2wzX2xlbiArPGJyPg0KLcKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgcGt0X2hlYWQtJmd0O2w0X2xlbjs8YnI+DQotwqAgwqAgwqAgwqBsMl9s ZW4gPSBsMl9vZmZzZXQgJmd0OyAwID8gcGt0X2hlYWQtJmd0O291dGVyX2wyX2xlbiA6IHBrdF9o ZWFkLSZndDtsMl9sZW47PGJyPg0KLcKgIMKgIMKgIMKgaWYgKHVubGlrZWx5KHBrdF9oZWFkLSZn dDtwa3RfbGVuIC0gbDJfbGVuICsgcGt0X3RhaWwtJmd0O3BrdF9sZW4gLTxicj4NCi3CoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGhkcl9sZW4gJmd0OyBNQVhf SVBWNF9QS1RfTEVOR1RIKSk8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gMDs8 YnI+DQotPGJyPg0KLcKgIMKgIMKgIMKgLyogcmVtb3ZlIHRoZSBwYWNrZXQgaGVhZGVyIGZvciB0 aGUgdGFpbCBwYWNrZXQgKi88YnI+DQotwqAgwqAgwqAgwqBydGVfcGt0bWJ1Zl9hZGoocGt0X3Rh aWwsIGhkcl9sZW4pOzxicj4NCi08YnI+DQotwqAgwqAgwqAgwqAvKiBjaGFpbiB0d28gcGFja2V0 cyB0b2dldGhlciAqLzxicj4NCi3CoCDCoCDCoCDCoGlmIChjbXAgJmd0OyAwKSB7PGJyPg0KLcKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgaXRlbS0mZ3Q7bGFzdHNlZy0mZ3Q7bmV4dCA9IHBrdDs8YnI+ DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpdGVtLSZndDtsYXN0c2VnID0gcnRlX3BrdG1idWZf bGFzdHNlZyhwa3QpOzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8qIHVwZGF0ZSBJUCBJ RCB0byB0aGUgbGFyZ2VyIHZhbHVlICovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaXRl bS0mZ3Q7aXBfaWQgPSBpcF9pZDs8YnI+DQotwqAgwqAgwqAgwqB9IGVsc2Ugezxicj4NCi3CoCDC oCDCoCDCoCDCoCDCoCDCoCDCoGxhc3RzZWcgPSBydGVfcGt0bWJ1Zl9sYXN0c2VnKHBrdCk7PGJy Pg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbGFzdHNlZy0mZ3Q7bmV4dCA9IGl0ZW0tJmd0O2Zp cnN0c2VnOzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW0tJmd0O2ZpcnN0c2VnID0g cGt0Ozxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8qIHVwZGF0ZSBzZW50X3NlcSB0byB0 aGUgc21hbGxlciB2YWx1ZSAqLzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW0tJmd0 O3NlbnRfc2VxID0gc2VudF9zZXE7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaXRlbS0m Z3Q7aXBfaWQgPSBpcF9pZDs8YnI+DQotwqAgwqAgwqAgwqB9PGJyPg0KLcKgIMKgIMKgIMKgaXRl bS0mZ3Q7bmJfbWVyZ2VkKys7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoC8qIHVwZGF0ZSBNQlVG IG1ldGFkYXRhIGZvciB0aGUgbWVyZ2VkIHBhY2tldCAqLzxicj4NCi3CoCDCoCDCoCDCoHBrdF9o ZWFkLSZndDtuYl9zZWdzICs9IHBrdF90YWlsLSZndDtuYl9zZWdzOzxicj4NCi3CoCDCoCDCoCDC oHBrdF9oZWFkLSZndDtwa3RfbGVuICs9IHBrdF90YWlsLSZndDtwa3RfbGVuOzxicj4NCi08YnI+ DQotwqAgwqAgwqAgwqByZXR1cm4gMTs8YnI+DQotfTxicj4NCi08YnI+DQotLyo8YnI+DQotICog Q2hlY2sgaWYgdHdvIFRDUC9JUHY0IHBhY2tldHMgYXJlIG5laWdoYm9ycy48YnI+DQotICovPGJy Pg0KLXN0YXRpYyBpbmxpbmUgaW50PGJyPg0KLWNoZWNrX3NlcV9vcHRpb24oc3RydWN0IGdyb190 Y3A0X2l0ZW0gKml0ZW0sPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc3RydWN0IHJ0ZV90 Y3BfaGRyICp0Y3BoLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRf c2VxLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGlwX2lkLDxicj4NCi3C oCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IHRjcF9obCw8YnI+DQotwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqB1aW50MTZfdCB0Y3BfZGwsPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg dWludDE2X3QgbDJfb2Zmc2V0LDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQ4X3Qg aXNfYXRvbWljKTxicj4NCi17PGJyPg0KLcKgIMKgIMKgIMKgc3RydWN0IHJ0ZV9tYnVmICpwa3Rf b3JpZyA9IGl0ZW0tJmd0O2ZpcnN0c2VnOzxicj4NCi3CoCDCoCDCoCDCoHN0cnVjdCBydGVfaXB2 NF9oZHIgKmlwaF9vcmlnOzxicj4NCi3CoCDCoCDCoCDCoHN0cnVjdCBydGVfdGNwX2hkciAqdGNw aF9vcmlnOzxicj4NCi3CoCDCoCDCoCDCoHVpbnQxNl90IGxlbiwgdGNwX2hsX29yaWc7PGJyPg0K LTxicj4NCi3CoCDCoCDCoCDCoGlwaF9vcmlnID0gKHN0cnVjdCBydGVfaXB2NF9oZHIgKikocnRl X3BrdG1idWZfbXRvZChwa3Rfb3JpZywgY2hhciAqKSArPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgbDJfb2Zmc2V0ICsgcGt0X29yaWctJmd0O2wyX2xlbik7PGJyPg0K LcKgIMKgIMKgIMKgdGNwaF9vcmlnID0gKHN0cnVjdCBydGVfdGNwX2hkciAqKSgoY2hhciAqKWlw aF9vcmlnICsgcGt0X29yaWctJmd0O2wzX2xlbik7PGJyPg0KLcKgIMKgIMKgIMKgdGNwX2hsX29y aWcgPSBwa3Rfb3JpZy0mZ3Q7bDRfbGVuOzxicj4NCi08YnI+DQotwqAgwqAgwqAgwqAvKiBDaGVj ayBpZiBUQ1Agb3B0aW9uIGZpZWxkcyBlcXVhbCAqLzxicj4NCi3CoCDCoCDCoCDCoGxlbiA9IFJU RV9NQVgodGNwX2hsLCB0Y3BfaGxfb3JpZykgLSBzaXplb2Yoc3RydWN0IHJ0ZV90Y3BfaGRyKTs8 YnI+DQotwqAgwqAgwqAgwqBpZiAoKHRjcF9obCAhPSB0Y3BfaGxfb3JpZykgfHwgKChsZW4gJmd0 OyAwKSAmYW1wOyZhbXA7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgKG1lbWNtcCh0Y3BoICsgMSwgdGNwaF9vcmlnICsgMSw8YnI+DQotwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBsZW4p ICE9IDApKSk8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gMDs8YnI+DQotPGJy Pg0KLcKgIMKgIMKgIMKgLyogRG9uJiMzOTt0IG1lcmdlIHBhY2tldHMgd2hvc2UgREYgYml0cyBh cmUgZGlmZmVyZW50ICovPGJyPg0KLcKgIMKgIMKgIMKgaWYgKHVubGlrZWx5KGl0ZW0tJmd0O2lz X2F0b21pYyBeIGlzX2F0b21pYykpPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJu IDA7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoC8qIGNoZWNrIGlmIHRoZSB0d28gcGFja2V0cyBh cmUgbmVpZ2hib3JzICovPGJyPg0KLcKgIMKgIMKgIMKgbGVuID0gcGt0X29yaWctJmd0O3BrdF9s ZW4gLSBsMl9vZmZzZXQgLSBwa3Rfb3JpZy0mZ3Q7bDJfbGVuIC08YnI+DQotwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBwa3Rfb3JpZy0mZ3Q7bDNfbGVuIC0gdGNwX2hsX29yaWc7PGJyPg0KLcKgIMKg IMKgIMKgaWYgKChzZW50X3NlcSA9PSBpdGVtLSZndDtzZW50X3NlcSArIGxlbikgJmFtcDsmYW1w OyAoaXNfYXRvbWljIHx8PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgKGlwX2lkID09IGl0ZW0tJmd0O2lwX2lkICsgMSkpKTxicj4NCi3CoCDCoCDC oCDCoCDCoCDCoCDCoCDCoC8qIGFwcGVuZCB0aGUgbmV3IHBhY2tldCAqLzxicj4NCi3CoCDCoCDC oCDCoCDCoCDCoCDCoCDCoHJldHVybiAxOzxicj4NCi3CoCDCoCDCoCDCoGVsc2UgaWYgKChzZW50 X3NlcSArIHRjcF9kbCA9PSBpdGVtLSZndDtzZW50X3NlcSkgJmFtcDsmYW1wOyAoaXNfYXRvbWlj IHx8PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg KGlwX2lkICsgaXRlbS0mZ3Q7bmJfbWVyZ2VkID09IGl0ZW0tJmd0O2lwX2lkKSkpPGJyPg0KLcKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgLyogcHJlLXBlbmQgdGhlIG5ldyBwYWNrZXQgKi88YnI+DQot wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gLTE7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDC oHJldHVybiAwOzxicj4NCi19PGJyPg0KwqAjZW5kaWY8YnI+DQpkaWZmIC0tZ2l0IGEvbGliL2dy by9ncm9fdGNwNi5jIGIvbGliL2dyby9ncm9fdGNwNi5jPGJyPg0KbmV3IGZpbGUgbW9kZSAxMDA2 NDQ8YnI+DQppbmRleCAwMDAwMDAwMDAwLi41YWEzOTgwMWUxPGJyPg0KLS0tIC9kZXYvbnVsbDxi cj4NCisrKyBiL2xpYi9ncm8vZ3JvX3RjcDYuYzxicj4NCkBAIC0wLDAgKzEsMjY4IEBAPGJyPg0K Ky8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMy1DbGF1c2U8YnI+DQorICogQ29weXJp Z2h0KGMpIDIwMjMgSW50ZWwgQ29ycG9yYXRpb248YnI+DQorICovPGJyPg0KKzxicj4NCisjaW5j bHVkZSAmbHQ7cnRlX21hbGxvYy5oJmd0Ozxicj4NCisjaW5jbHVkZSAmbHQ7cnRlX21idWYuaCZn dDs8YnI+DQorI2luY2x1ZGUgJmx0O3J0ZV9ldGhkZXYuaCZndDs8YnI+DQorPGJyPg0KKyNpbmNs dWRlICZxdW90O2dyb190Y3A2LmgmcXVvdDs8YnI+DQorI2luY2x1ZGUgJnF1b3Q7Z3JvX3RjcF9p bnRlcm5hbC5oJnF1b3Q7PGJyPg0KKzxicj4NCit2b2lkICo8YnI+DQorZ3JvX3RjcDZfdGJsX2Ny ZWF0ZSh1aW50MTZfdCBzb2NrZXRfaWQsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWlu dDE2X3QgbWF4X2Zsb3dfbnVtLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90 IG1heF9pdGVtX3Blcl9mbG93KTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IGdyb190 Y3A2X3RibCAqdGJsOzxicj4NCivCoCDCoCDCoCDCoHNpemVfdCBzaXplOzxicj4NCivCoCDCoCDC oCDCoHVpbnQzMl90IGVudHJpZXNfbnVtLCBpOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBlbnRy aWVzX251bSA9IG1heF9mbG93X251bSAqIG1heF9pdGVtX3Blcl9mbG93Ozxicj4NCivCoCDCoCDC oCDCoGVudHJpZXNfbnVtID0gUlRFX01JTihlbnRyaWVzX251bSwgR1JPX1RDUDZfVEJMX01BWF9J VEVNX05VTSk7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGlmIChlbnRyaWVzX251bSA9PSAwKTxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBOVUxMOzxicj4NCis8YnI+DQorwqAg wqAgwqAgwqB0YmwgPSBydGVfem1hbGxvY19zb2NrZXQoX19mdW5jX18sPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc2l6ZW9mKHN0cnVjdCBncm9fdGNwNl90YmwpLDxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoFJURV9DQUNIRV9MSU5FX1NJ WkUsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc29ja2V0X2lkKTs8 YnI+DQorwqAgwqAgwqAgwqBpZiAodGJsID09IE5VTEwpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgcmV0dXJuIE5VTEw7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoHNpemUgPSBzaXplb2Yo c3RydWN0IGdyb190Y3BfaXRlbSkgKiBlbnRyaWVzX251bTs8YnI+DQorwqAgwqAgwqAgwqB0Ymwt Jmd0O2l0ZW1zID0gcnRlX3ptYWxsb2Nfc29ja2V0KF9fZnVuY19fLDxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHNpemUsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgUlRFX0NBQ0hFX0xJTkVfU0laRSw8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqBzb2NrZXRfaWQpOzxicj4NCivCoCDCoCDCoCDCoGlmICh0Ymwt Jmd0O2l0ZW1zID09IE5VTEwpIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBydGVfZnJl ZSh0YmwpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBOVUxMOzxicj4NCivC oCDCoCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqB0YmwtJmd0O21heF9pdGVtX251bSA9IGVudHJp ZXNfbnVtOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBzaXplID0gc2l6ZW9mKHN0cnVjdCBncm9f dGNwNl9mbG93KSAqIGVudHJpZXNfbnVtOzxicj4NCivCoCDCoCDCoCDCoHRibC0mZ3Q7Zmxvd3Mg PSBydGVfem1hbGxvY19zb2NrZXQoX19mdW5jX18sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgc2l6ZSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBSVEVfQ0FDSEVfTElORV9TSVpFLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoHNvY2tldF9pZCk7PGJyPg0KK8KgIMKgIMKgIMKgaWYgKHRibC0mZ3Q7Zmxvd3Mg PT0gTlVMTCkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJ0ZV9mcmVlKHRibC0mZ3Q7 aXRlbXMpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJ0ZV9mcmVlKHRibCk7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIE5VTEw7PGJyPg0KK8KgIMKgIMKgIMKgfTxi cj4NCivCoCDCoCDCoCDCoC8qIElOVkFMSURfQVJSQVlfSU5ERVggaW5kaWNhdGVzIGFuIGVtcHR5 IGZsb3cgKi88YnI+DQorwqAgwqAgwqAgwqBmb3IgKGkgPSAwOyBpICZsdDsgZW50cmllc19udW07 IGkrKyk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0YmwtJmd0O2Zsb3dzW2ldLnN0YXJ0 X2luZGV4ID0gSU5WQUxJRF9BUlJBWV9JTkRFWDs8YnI+DQorwqAgwqAgwqAgwqB0YmwtJmd0O21h eF9mbG93X251bSA9IGVudHJpZXNfbnVtOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqByZXR1cm4g dGJsOzxicj4NCit9PGJyPg0KKzxicj4NCit2b2lkPGJyPg0KK2dyb190Y3A2X3RibF9kZXN0cm95 KHZvaWQgKnRibCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBncm9fdGNwNl90Ymwg KnRjcF90YmwgPSB0Ymw7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGlmICh0Y3BfdGJsKSB7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcnRlX2ZyZWUodGNwX3RibC0mZ3Q7aXRlbXMpOzxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJ0ZV9mcmVlKHRjcF90YmwtJmd0O2Zsb3dzKTs8 YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KK8KgIMKgIMKgIMKgcnRlX2ZyZWUodGNwX3RibCk7PGJy Pg0KK308YnI+DQorPGJyPg0KK3N0YXRpYyBpbmxpbmUgdWludDMyX3Q8YnI+DQorZmluZF9hbl9l bXB0eV9mbG93KHN0cnVjdCBncm9fdGNwNl90YmwgKnRibCk8YnI+DQorezxicj4NCivCoCDCoCDC oCDCoHVpbnQzMl90IGk7PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgbWF4X2Zsb3dfbnVtID0g dGJsLSZndDttYXhfZmxvd19udW07PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGZvciAoaSA9IDA7 IGkgJmx0OyBtYXhfZmxvd19udW07IGkrKyk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBp ZiAodGJsLSZndDtmbG93c1tpXS5zdGFydF9pbmRleCA9PSBJTlZBTElEX0FSUkFZX0lOREVYKTxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBpOzxicj4NCivC oCDCoCDCoCDCoHJldHVybiBJTlZBTElEX0FSUkFZX0lOREVYOzxicj4NCit9PGJyPg0KKzxicj4N CitzdGF0aWMgaW5saW5lIHVpbnQzMl90PGJyPg0KK2luc2VydF9uZXdfZmxvdyhzdHJ1Y3QgZ3Jv X3RjcDZfdGJsICp0YmwsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc3RydWN0IHRjcDZf Zmxvd19rZXkgKnNyYyw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MzJfdCBpdGVt X2lkeCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCB0Y3A2X2Zsb3dfa2V5ICpkc3Q7 PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgZmxvd19pZHg7PGJyPg0KKzxicj4NCivCoCDCoCDC oCDCoGZsb3dfaWR4ID0gZmluZF9hbl9lbXB0eV9mbG93KHRibCk7PGJyPg0KK8KgIMKgIMKgIMKg aWYgKHVubGlrZWx5KGZsb3dfaWR4ID09IElOVkFMSURfQVJSQVlfSU5ERVgpKTxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBJTlZBTElEX0FSUkFZX0lOREVYOzxicj4NCis8YnI+ DQorwqAgwqAgwqAgwqBkc3QgPSAmYW1wOyh0YmwtJmd0O2Zsb3dzW2Zsb3dfaWR4XS5rZXkpOzxi cj4NCis8YnI+DQorwqAgwqAgwqAgwqBBU1NJR05fQ09NTU9OX1RDUF9LRVkoKCZhbXA7c3JjLSZn dDtjbW5fa2V5KSwgKCZhbXA7ZHN0LSZndDtjbW5fa2V5KSk7PGJyPg0KK8KgIMKgIMKgIMKgbWVt Y3B5KCZhbXA7ZHN0LSZndDtzcmNfYWRkclswXSwgJmFtcDtzcmMtJmd0O3NyY19hZGRyWzBdLCBz aXplb2YoZHN0LSZndDtzcmNfYWRkcikpOzxicj4NCivCoCDCoCDCoCDCoG1lbWNweSgmYW1wO2Rz dC0mZ3Q7ZHN0X2FkZHJbMF0sICZhbXA7c3JjLSZndDtkc3RfYWRkclswXSwgc2l6ZW9mKGRzdC0m Z3Q7ZHN0X2FkZHIpKTs8YnI+DQorwqAgwqAgwqAgwqBkc3QtJmd0O3Z0Y19mbG93ID0gc3JjLSZn dDt2dGNfZmxvdzs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgdGJsLSZndDtmbG93c1tmbG93X2lk eF0uc3RhcnRfaW5kZXggPSBpdGVtX2lkeDs8YnI+DQorwqAgwqAgwqAgwqB0YmwtJmd0O2Zsb3df bnVtKys7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoHJldHVybiBmbG93X2lkeDs8YnI+DQorfTxi cj4NCis8YnI+DQorLyo8YnI+DQorICogdXBkYXRlIHRoZSBwYWNrZXQgbGVuZ3RoIGZvciB0aGUg Zmx1c2hlZCBwYWNrZXQuPGJyPg0KKyAqLzxicj4NCitzdGF0aWMgaW5saW5lIHZvaWQ8YnI+DQor dXBkYXRlX2hlYWRlcihzdHJ1Y3QgZ3JvX3RjcF9pdGVtICppdGVtKTxicj4NCit7PGJyPg0KK8Kg IMKgIMKgIMKgc3RydWN0IHJ0ZV9pcHY2X2hkciAqaXB2Nl9oZHI7PGJyPg0KK8KgIMKgIMKgIMKg c3RydWN0IHJ0ZV9tYnVmICpwa3QgPSBpdGVtLSZndDtmaXJzdHNlZzs8YnI+DQorPGJyPg0KK8Kg IMKgIMKgIMKgaXB2Nl9oZHIgPSAoc3RydWN0IHJ0ZV9pcHY2X2hkciAqKShydGVfcGt0bWJ1Zl9t dG9kKHBrdCwgY2hhciAqKSArPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgcGt0LSZndDtsMl9sZW4pOzxicj4NCivCoCDCoCDCoCDCoGlwdjZfaGRyLSZndDtwYXlsb2Fk X2xlbiA9IHJ0ZV9jcHVfdG9fYmVfMTYocGt0LSZndDtwa3RfbGVuIC08YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3QtJmd0O2wyX2xlbiAtIHBrdC0mZ3Q7bDNfbGVu KTs8YnI+DQorfTxicj4NCis8YnI+DQoraW50MzJfdDxicj4NCitncm9fdGNwNl9yZWFzc2VtYmxl KHN0cnVjdCBydGVfbWJ1ZiAqcGt0LDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHN0cnVj dCBncm9fdGNwNl90YmwgKnRibCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50NjRf dCBzdGFydF90aW1lKTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IHJ0ZV9ldGhlcl9o ZHIgKmV0aF9oZHI7PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IHJ0ZV9pcHY2X2hkciAqaXB2Nl9o ZHI7PGJyPg0KK8KgIMKgIMKgIMKgaW50MzJfdCB0Y3BfZGw7PGJyPg0KK8KgIMKgIMKgIMKgdWlu dDE2X3QgaXBfdGxlbjs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgdGNwNl9mbG93X2tleSBrZXk7 PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgaSwgbWF4X2Zsb3dfbnVtLCByZW1haW5pbmdfZmxv d19udW07PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3Qgc2VudF9zZXE7PGJyPg0KK8KgIMKgIMKg IMKgc3RydWN0IHJ0ZV90Y3BfaGRyICp0Y3BfaGRyOzxicj4NCivCoCDCoCDCoCDCoHVpbnQ4X3Qg ZmluZDs8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBpdGVtX2lkeDs8YnI+DQorwqAgwqAgwqAg wqAvKjxicj4NCivCoCDCoCDCoCDCoCAqIERvbiYjMzk7dCBwcm9jZXNzIHRoZSBwYWNrZXQgd2hv c2UgVENQIGhlYWRlciBsZW5ndGggaXMgZ3JlYXRlcjxicj4NCivCoCDCoCDCoCDCoCAqIHRoYW4g NjAgYnl0ZXMgb3IgbGVzcyB0aGFuIDIwIGJ5dGVzLjxicj4NCivCoCDCoCDCoCDCoCAqLzxicj4N CivCoCDCoCDCoCDCoGlmICh1bmxpa2VseShJTlZBTElEX1RDUF9IRFJMRU4ocGt0LSZndDtsNF9s ZW4pKSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gLTE7PGJyPg0KKzxicj4N CivCoCDCoCDCoCDCoGV0aF9oZHIgPSBydGVfcGt0bWJ1Zl9tdG9kKHBrdCwgc3RydWN0IHJ0ZV9l dGhlcl9oZHIgKik7PGJyPg0KK8KgIMKgIMKgIMKgaXB2Nl9oZHIgPSAoc3RydWN0IHJ0ZV9pcHY2 X2hkciAqKSgoY2hhciAqKWV0aF9oZHIgKyBwa3QtJmd0O2wyX2xlbik7PGJyPg0KK8KgIMKgIMKg IMKgdGNwX2hkciA9IHJ0ZV9wa3RtYnVmX210b2Rfb2Zmc2V0KHBrdCwgc3RydWN0IHJ0ZV90Y3Bf aGRyICosIHBrdC0mZ3Q7bDJfbGVuICsgcGt0LSZndDtsM19sZW4pOzxicj4NCis8YnI+DQorwqAg wqAgwqAgwqAvKjxicj4NCivCoCDCoCDCoCDCoCAqIERvbiYjMzk7dCBwcm9jZXNzIHRoZSBwYWNr ZXQgd2hpY2ggaGFzIEZJTiwgU1lOLCBSU1QsIFBTSCwgVVJHLCBFQ0U8YnI+DQorwqAgwqAgwqAg wqAgKiBvciBDV1Igc2V0Ljxicj4NCivCoCDCoCDCoCDCoCAqLzxicj4NCivCoCDCoCDCoCDCoGlm ICh0Y3BfaGRyLSZndDt0Y3BfZmxhZ3MgIT0gUlRFX1RDUF9BQ0tfRkxBRyk8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gLTE7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGlwX3Rs ZW4gPSBydGVfYmVfdG9fY3B1XzE2KGlwdjZfaGRyLSZndDtwYXlsb2FkX2xlbik7PGJyPg0KK8Kg IMKgIMKgIMKgLyo8YnI+DQorwqAgwqAgwqAgwqAgKiBEb24mIzM5O3QgcHJvY2VzcyB0aGUgcGFj a2V0IHdob3NlIHBheWxvYWQgbGVuZ3RoIGlzIGxlc3MgdGhhbiBvcjxicj4NCivCoCDCoCDCoCDC oCAqIGVxdWFsIHRvIDAuPGJyPg0KK8KgIMKgIMKgIMKgICovPGJyPg0KK8KgIMKgIMKgIMKgdGNw X2RsID0gaXBfdGxlbiAtIHBrdC0mZ3Q7bDRfbGVuOzxicj4NCivCoCDCoCDCoCDCoGlmICh0Y3Bf ZGwgJmx0Oz0gMCk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gLTE7PGJyPg0K Kzxicj4NCivCoCDCoCDCoCDCoHJ0ZV9ldGhlcl9hZGRyX2NvcHkoJmFtcDsoZXRoX2hkci0mZ3Q7 c3JjX2FkZHIpLCAmYW1wOyhrZXkuY21uX2tleS5ldGhfc2FkZHIpKTs8YnI+DQorwqAgwqAgwqAg wqBydGVfZXRoZXJfYWRkcl9jb3B5KCZhbXA7KGV0aF9oZHItJmd0O2RzdF9hZGRyKSwgJmFtcDso a2V5LmNtbl9rZXkuZXRoX2RhZGRyKSk7PGJyPg0KK8KgIMKgIMKgIMKgbWVtY3B5KCZhbXA7a2V5 LnNyY19hZGRyWzBdLCAmYW1wO2lwdjZfaGRyLSZndDtzcmNfYWRkciwgc2l6ZW9mKGtleS5zcmNf YWRkcikpOzxicj4NCivCoCDCoCDCoCDCoG1lbWNweSgmYW1wO2tleS5kc3RfYWRkclswXSwgJmFt cDtpcHY2X2hkci0mZ3Q7ZHN0X2FkZHIsIHNpemVvZihrZXkuZHN0X2FkZHIpKTs8YnI+DQorwqAg wqAgwqAgwqBrZXkuY21uX2tleS5zcmNfcG9ydCA9IHRjcF9oZHItJmd0O3NyY19wb3J0Ozxicj4N CivCoCDCoCDCoCDCoGtleS5jbW5fa2V5LmRzdF9wb3J0ID0gdGNwX2hkci0mZ3Q7ZHN0X3BvcnQ7 PGJyPg0KK8KgIMKgIMKgIMKga2V5LmNtbl9rZXkucmVjdl9hY2sgPSB0Y3BfaGRyLSZndDtyZWN2 X2Fjazs8YnI+DQorwqAgwqAgwqAgwqBrZXkudnRjX2Zsb3cgPSBpcHY2X2hkci0mZ3Q7dnRjX2Zs b3c7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoC8qIFNlYXJjaCBmb3IgYSBtYXRjaGVkIGZsb3cu ICovPGJyPg0KK8KgIMKgIMKgIMKgbWF4X2Zsb3dfbnVtID0gdGJsLSZndDttYXhfZmxvd19udW07 PGJyPg0KK8KgIMKgIMKgIMKgcmVtYWluaW5nX2Zsb3dfbnVtID0gdGJsLSZndDtmbG93X251bTs8 YnI+DQorwqAgwqAgwqAgwqBmaW5kID0gMDs8YnI+DQorwqAgwqAgwqAgwqBmb3IgKGkgPSAwOyBp ICZsdDsgbWF4X2Zsb3dfbnVtICZhbXA7JmFtcDsgcmVtYWluaW5nX2Zsb3dfbnVtOyBpKyspIHs8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAodGJsLSZndDtmbG93c1tpXS5zdGFydF9p bmRleCAhPSBJTlZBTElEX0FSUkFZX0lOREVYKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgaWYgKGlzX3NhbWVfdGNwNl9mbG93KCZhbXA7dGJsLSZndDtmbG93c1tp XS5rZXksICZhbXA7a2V5KSkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoGZpbmQgPSAxOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoGJyZWFrOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBy ZW1haW5pbmdfZmxvd19udW0tLTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0K K8KgIMKgIMKgIMKgfTxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBpZiAoZmluZCA9PSAwKSB7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc2VudF9zZXEgPSBydGVfYmVfdG9fY3B1XzMyKHRj cF9oZHItJmd0O3NlbnRfc2VxKTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpdGVtX2lk eCA9IGluc2VydF9uZXdfdGNwX2l0ZW0ocGt0LCB0YmwtJmd0O2l0ZW1zLCAmYW1wO3RibC0mZ3Q7 aXRlbV9udW0sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGJsLSZndDttYXhfaXRlbV9udW0sIHN0YXJ0 X3RpbWUsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgSU5WQUxJRF9BUlJBWV9JTkRFWCwgc2VudF9zZXEs IDAsIHRydWUpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChpdGVtX2lkeCA9PSBJ TlZBTElEX0FSUkFZX0lOREVYKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoHJldHVybiAtMTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoaW5zZXJ0X25l d19mbG93KHRibCwgJmFtcDtrZXksIGl0ZW1faWR4KSA9PTxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoElOVkFMSURfQVJSQVlfSU5ERVgpIHs8YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKjxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCAqIEZhaWwgdG8gaW5zZXJ0IGEgbmV3IGZsb3csIHNvIGRlbGV0ZSB0aGU8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKiBzdG9yZWQgcGFja2V0 Ljxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqLzxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGRlbGV0ZV90Y3BfaXRlbSh0YmwtJmd0O2l0 ZW1zLCBpdGVtX2lkeCwgJmFtcDt0YmwtJmd0O2l0ZW1fbnVtLCBJTlZBTElEX0FSUkFZX0lOREVY KTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gLTE7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oHJldHVybiAwOzxicj4NCivCoCDCoCDCoCDCoH08YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgcmV0 dXJuIHByb2Nlc3NfdGNwX2l0ZW0ocGt0LCB0Y3BfaGRyLCB0Y3BfZGwsIHRibC0mZ3Q7aXRlbXMs IHRibC0mZ3Q7Zmxvd3NbaV0uc3RhcnRfaW5kZXgsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgJmFtcDt0 YmwtJmd0O2l0ZW1fbnVtLCB0YmwtJmd0O21heF9pdGVtX251bSw8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAwLCB0cnVlLCBzdGFydF90aW1lKTs8YnI+DQorfTxicj4NCis8YnI+DQordWludDE2X3Q8YnI+ DQorZ3JvX3RjcDZfdGJsX3RpbWVvdXRfZmx1c2goc3RydWN0IGdyb190Y3A2X3RibCAqdGJsLDxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQ2NF90IGZsdXNoX3RpbWVzdGFtcCw8YnI+ DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX21idWYgKipvdXQsPGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDE2X3QgbmJfb3V0KTxicj4NCit7PGJyPg0KK8KgIMKg IMKgIMKgdWludDE2X3QgayA9IDA7PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgaSwgajs8YnI+ DQorwqAgwqAgwqAgwqB1aW50MzJfdCBtYXhfZmxvd19udW0gPSB0YmwtJmd0O21heF9mbG93X251 bTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgZm9yIChpID0gMDsgaSAmbHQ7IG1heF9mbG93X251 bTsgaSsrKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKHVubGlrZWx5KHRibC0m Z3Q7Zmxvd19udW0gPT0gMCkpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgcmV0dXJuIGs7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGogPSB0Ymwt Jmd0O2Zsb3dzW2ldLnN0YXJ0X2luZGV4Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHdo aWxlIChqICE9IElOVkFMSURfQVJSQVlfSU5ERVgpIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBpZiAodGJsLSZndDtpdGVtc1tqXS5zdGFydF90aW1lICZsdDs9IGZs dXNoX3RpbWVzdGFtcCkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoG91dFtrKytdID0gdGJsLSZndDtpdGVtc1tqXS5maXJzdHNlZzs8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAodGJsLSZn dDtpdGVtc1tqXS5uYl9tZXJnZWQgJmd0OyAxKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVwZGF0ZV9oZWFkZXIoJmFtcDso dGJsLSZndDtpdGVtc1tqXSkpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoC8qPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgICogRGVsZXRlIHRoZSBwYWNrZXQgYW5kIGdldCB0aGUgbmV4dDxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqIHBhY2tl dCBpbiB0aGUgZmxvdy48YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBqID0gZGVsZXRlX3RjcF9pdGVtKHRibC0mZ3Q7aXRlbXMsIGosPGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgJmFtcDt0YmwtJmd0O2l0ZW1fbnVtLCBJTlZBTElEX0FSUkFZX0lOREVYKTs8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0Ymwt Jmd0O2Zsb3dzW2ldLnN0YXJ0X2luZGV4ID0gajs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoaiA9PSBJTlZBTElEX0FSUkFZX0lOREVYKTxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoHRibC0mZ3Q7Zmxvd19udW0tLTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKHVubGlrZWx5KGsgPT0gbmJfb3V0KSk8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqByZXR1cm4gazs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqB9IGVsc2U8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAvKjxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCAqIFRoZSBsZWZ0IHBhY2tldHMgaW4gdGhpcyBmbG93IHdvbiYjMzk7dCBiZTxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqIHRpbWVvdXQu IEdvIHRvIGNoZWNrIG90aGVyIGZsb3dzLjxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqLzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoGJyZWFrOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oH08YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIGs7PGJyPg0KK308 YnI+DQorPGJyPg0KK3VpbnQzMl90PGJyPg0KK2dyb190Y3A2X3RibF9wa3RfY291bnQodm9pZCAq dGJsKTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IGdyb190Y3A2X3RibCAqZ3JvX3Ri bCA9IHRibDs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgaWYgKGdyb190YmwpPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIGdyb190YmwtJmd0O2l0ZW1fbnVtOzxicj4NCis8YnI+ DQorwqAgwqAgwqAgwqByZXR1cm4gMDs8YnI+DQorfTxicj4NCmRpZmYgLS1naXQgYS9saWIvZ3Jv L2dyb190Y3A2LmggYi9saWIvZ3JvL2dyb190Y3A2Lmg8YnI+DQpuZXcgZmlsZSBtb2RlIDEwMDY0 NDxicj4NCmluZGV4IDAwMDAwMDAwMDAuLjA3MzEyMmYwZWM8YnI+DQotLS0gL2Rldi9udWxsPGJy Pg0KKysrIGIvbGliL2dyby9ncm9fdGNwNi5oPGJyPg0KQEAgLTAsMCArMSwxNjAgQEA8YnI+DQor LyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEJTRC0zLUNsYXVzZTxicj4NCisgKiBDb3B5cmln aHQoYykgMjAyMyBJbnRlbCBDb3Jwb3JhdGlvbjxicj4NCisgKi88YnI+DQorPGJyPg0KKyNpZm5k ZWYgX0dST19UQ1A2X0hfPGJyPg0KKyNkZWZpbmUgX0dST19UQ1A2X0hfPGJyPg0KKzxicj4NCisj aW5jbHVkZSAmcXVvdDtncm9fdGNwLmgmcXVvdDs8YnI+DQorPGJyPg0KKyNkZWZpbmUgR1JPX1RD UDZfVEJMX01BWF9JVEVNX05VTSAoMTAyNFVMICogMTAyNFVMKTxicj4NCis8YnI+DQorLyogSGVh ZGVyIGZpZWxkcyByZXByZXNlbnRpbmcgYSBUQ1AvSVB2NiBmbG93ICovPGJyPg0KK3N0cnVjdCB0 Y3A2X2Zsb3dfa2V5IHs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgY21uX3RjcF9rZXkgY21uX2tl eTs8YnI+DQorwqAgwqAgwqAgwqB1aW50OF90wqAgc3JjX2FkZHJbMTZdOzxicj4NCivCoCDCoCDC oCDCoHVpbnQ4X3TCoCBkc3RfYWRkclsxNl07PGJyPg0KK8KgIMKgIMKgIMKgcnRlX2JlMzJfdCB2 dGNfZmxvdzs8YnI+DQorfTs8YnI+DQorPGJyPg0KK3N0cnVjdCBncm9fdGNwNl9mbG93IHs8YnI+ DQorwqAgwqAgwqAgwqBzdHJ1Y3QgdGNwNl9mbG93X2tleSBrZXk7PGJyPg0KK8KgIMKgIMKgIMKg Lyo8YnI+DQorwqAgwqAgwqAgwqAgKiBUaGUgaW5kZXggb2YgdGhlIGZpcnN0IHBhY2tldCBpbiB0 aGUgZmxvdy48YnI+DQorwqAgwqAgwqAgwqAgKiBJTlZBTElEX0FSUkFZX0lOREVYIGluZGljYXRl cyBhbiBlbXB0eSBmbG93Ljxicj4NCivCoCDCoCDCoCDCoCAqLzxicj4NCivCoCDCoCDCoCDCoHVp bnQzMl90IHN0YXJ0X2luZGV4Ozxicj4NCit9Ozxicj4NCis8YnI+DQorLyo8YnI+DQorICogVENQ L0lQdjYgcmVhc3NlbWJseSB0YWJsZSBzdHJ1Y3R1cmUuPGJyPg0KKyAqLzxicj4NCitzdHJ1Y3Qg Z3JvX3RjcDZfdGJsIHs8YnI+DQorwqAgwqAgwqAgwqAvKiBpdGVtIGFycmF5ICovPGJyPg0KK8Kg IMKgIMKgIMKgc3RydWN0IGdyb190Y3BfaXRlbSAqaXRlbXM7PGJyPg0KK8KgIMKgIMKgIMKgLyog ZmxvdyBhcnJheSAqLzxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBncm9fdGNwNl9mbG93ICpmbG93 czs8YnI+DQorwqAgwqAgwqAgwqAvKiBjdXJyZW50IGl0ZW0gbnVtYmVyICovPGJyPg0KK8KgIMKg IMKgIMKgdWludDMyX3QgaXRlbV9udW07PGJyPg0KK8KgIMKgIMKgIMKgLyogY3VycmVudCBmbG93 IG51bSAqLzxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IGZsb3dfbnVtOzxicj4NCivCoCDCoCDC oCDCoC8qIGl0ZW0gYXJyYXkgc2l6ZSAqLzxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IG1heF9p dGVtX251bTs8YnI+DQorwqAgwqAgwqAgwqAvKiBmbG93IGFycmF5IHNpemUgKi88YnI+DQorwqAg wqAgwqAgwqB1aW50MzJfdCBtYXhfZmxvd19udW07PGJyPg0KK307PGJyPg0KKzxicj4NCisvKio8 YnI+DQorICogVGhpcyBmdW5jdGlvbiBjcmVhdGVzIGEgVENQL0lQdjYgcmVhc3NlbWJseSB0YWJs ZS48YnI+DQorICo8YnI+DQorICogQHBhcmFtIHNvY2tldF9pZDxicj4NCisgKsKgIFNvY2tldCBp bmRleCBmb3IgYWxsb2NhdGluZyB0aGUgVENQL0lQdjYgcmVhc3NlbWJsZSB0YWJsZTxicj4NCisg KiBAcGFyYW0gbWF4X2Zsb3dfbnVtPGJyPg0KKyAqwqAgVGhlIG1heGltdW0gbnVtYmVyIG9mIGZs b3dzIGluIHRoZSBUQ1AvSVB2NiBHUk8gdGFibGU8YnI+DQorICogQHBhcmFtIG1heF9pdGVtX3Bl cl9mbG93PGJyPg0KKyAqwqAgVGhlIG1heGltdW0gbnVtYmVyIG9mIHBhY2tldHMgcGVyIGZsb3c8 YnI+DQorICo8YnI+DQorICogQHJldHVybjxicj4NCisgKsKgIC0gUmV0dXJuIHRoZSB0YWJsZSBw b2ludGVyIG9uIHN1Y2Nlc3MuPGJyPg0KKyAqwqAgLSBSZXR1cm4gTlVMTCBvbiBmYWlsdXJlLjxi cj4NCisgKi88YnI+DQordm9pZCAqZ3JvX3RjcDZfdGJsX2NyZWF0ZSh1aW50MTZfdCBzb2NrZXRf aWQsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDE2X3QgbWF4X2Zsb3dfbnVtLDxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IG1heF9pdGVtX3Blcl9mbG93KTs8 YnI+DQorPGJyPg0KKy8qKjxicj4NCisgKiBUaGlzIGZ1bmN0aW9uIGRlc3Ryb3lzIGEgVENQL0lQ djYgcmVhc3NlbWJseSB0YWJsZS48YnI+DQorICo8YnI+DQorICogQHBhcmFtIHRibDxicj4NCisg KsKgIFBvaW50ZXIgcG9pbnRpbmcgdG8gdGhlIFRDUC9JUHY2IHJlYXNzZW1ibHkgdGFibGUuPGJy Pg0KKyAqLzxicj4NCit2b2lkIGdyb190Y3A2X3RibF9kZXN0cm95KHZvaWQgKnRibCk7PGJyPg0K Kzxicj4NCisvKio8YnI+DQorICogVGhpcyBmdW5jdGlvbiBtZXJnZXMgYSBUQ1AvSVB2NiBwYWNr ZXQuIEl0IGRvZXNuJiMzOTt0IHByb2Nlc3MgdGhlIHBhY2tldCw8YnI+DQorICogd2hpY2ggaGFz IFNZTiwgRklOLCBSU1QsIFBTSCwgQ1dSLCBFQ0Ugb3IgVVJHIHNldCwgb3IgZG9lc24mIzM5O3Qg aGF2ZTxicj4NCisgKiBwYXlsb2FkLjxicj4NCisgKjxicj4NCisgKiBUaGlzIGZ1bmN0aW9uIGRv ZXNuJiMzOTt0IGNoZWNrIGlmIHRoZSBwYWNrZXQgaGFzIGNvcnJlY3QgY2hlY2tzdW1zIGFuZDxi cj4NCisgKiBkb2VzbiYjMzk7dCByZS1jYWxjdWxhdGUgY2hlY2tzdW1zIGZvciB0aGUgbWVyZ2Vk IHBhY2tldC4gQWRkaXRpb25hbGx5LDxicj4NCisgKiBpdCBhc3N1bWVzIHRoZSBwYWNrZXRzIGFy ZSBjb21wbGV0ZSAoaS5lLiwgTUY9PTAgJmFtcDsmYW1wOyBmcmFnX29mZj09MCksPGJyPg0KKyAq IHdoZW4gSVAgZnJhZ21lbnRhdGlvbiBpcyBwb3NzaWJsZSAoaS5lLiwgREY9PTApLiBJdCByZXR1 cm5zIHRoZTxicj4NCisgKiBwYWNrZXQsIGlmIHRoZSBwYWNrZXQgaGFzIGludmFsaWQgcGFyYW1l dGVycyAoZS5nLiBTWU4gYml0IGlzIHNldCk8YnI+DQorICogb3IgdGhlcmUgaXMgbm8gYXZhaWxh YmxlIHNwYWNlIGluIHRoZSB0YWJsZS48YnI+DQorICo8YnI+DQorICogQHBhcmFtIHBrdDxicj4N CisgKsKgIFBhY2tldCB0byByZWFzc2VtYmxlPGJyPg0KKyAqIEBwYXJhbSB0Ymw8YnI+DQorICrC oCBQb2ludGVyIHBvaW50aW5nIHRvIHRoZSBUQ1AvSVB2NiByZWFzc2VtYmx5IHRhYmxlPGJyPg0K KyAqIEBzdGFydF90aW1lPGJyPg0KKyAqwqAgVGhlIHRpbWUgd2hlbiB0aGUgcGFja2V0IGlzIGlu c2VydGVkIGludG8gdGhlIHRhYmxlPGJyPg0KKyAqPGJyPg0KKyAqIEByZXR1cm48YnI+DQorICrC oCAtIFJldHVybiBhIHBvc2l0aXZlIHZhbHVlIGlmIHRoZSBwYWNrZXQgaXMgbWVyZ2VkLjxicj4N CisgKsKgIC0gUmV0dXJuIHplcm8gaWYgdGhlIHBhY2tldCBpc24mIzM5O3QgbWVyZ2VkIGJ1dCBz dG9yZWQgaW4gdGhlIHRhYmxlLjxicj4NCisgKsKgIC0gUmV0dXJuIGEgbmVnYXRpdmUgdmFsdWUg Zm9yIGludmFsaWQgcGFyYW1ldGVycyBvciBubyBhdmFpbGFibGU8YnI+DQorICrCoCDCoCBzcGFj ZSBpbiB0aGUgdGFibGUuPGJyPg0KKyAqLzxicj4NCitpbnQzMl90IGdyb190Y3A2X3JlYXNzZW1i bGUoc3RydWN0IHJ0ZV9tYnVmICpwa3QsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc3Ry dWN0IGdyb190Y3A2X3RibCAqdGJsLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQ2 NF90IHN0YXJ0X3RpbWUpOzxicj4NCis8YnI+DQorLyoqPGJyPg0KKyAqIFRoaXMgZnVuY3Rpb24g Zmx1c2hlcyB0aW1lb3V0IHBhY2tldHMgaW4gYSBUQ1AvSVB2NiByZWFzc2VtYmx5IHRhYmxlLDxi cj4NCisgKiBhbmQgd2l0aG91dCB1cGRhdGluZyBjaGVja3N1bXMuPGJyPg0KKyAqPGJyPg0KKyAq IEBwYXJhbSB0Ymw8YnI+DQorICrCoCBUQ1AvSVB2NiByZWFzc2VtYmx5IHRhYmxlIHBvaW50ZXI8 YnI+DQorICogQHBhcmFtIGZsdXNoX3RpbWVzdGFtcDxicj4NCisgKsKgIEZsdXNoIHBhY2tldHMg d2hpY2ggYXJlIGluc2VydGVkIGludG8gdGhlIHRhYmxlIGJlZm9yZSBvciBhdCB0aGU8YnI+DQor ICrCoCBmbHVzaF90aW1lc3RhbXAuPGJyPg0KKyAqIEBwYXJhbSBvdXQ8YnI+DQorICrCoCBQb2lu dGVyIGFycmF5IHVzZWQgdG8ga2VlcCBmbHVzaGVkIHBhY2tldHM8YnI+DQorICogQHBhcmFtIG5i X291dDxicj4NCisgKsKgIFRoZSBlbGVtZW50IG51bWJlciBpbiAmIzM5O291dCYjMzk7LiBJdCBh bHNvIGRldGVybWluZXMgdGhlIG1heGltdW0gbnVtYmVyIG9mPGJyPg0KKyAqwqAgcGFja2V0cyB0 aGF0IGNhbiBiZSBmbHVzaGVkIGZpbmFsbHkuPGJyPg0KKyAqPGJyPg0KKyAqIEByZXR1cm48YnI+ DQorICrCoCBUaGUgbnVtYmVyIG9mIGZsdXNoZWQgcGFja2V0czxicj4NCisgKi88YnI+DQordWlu dDE2X3QgZ3JvX3RjcDZfdGJsX3RpbWVvdXRfZmx1c2goc3RydWN0IGdyb190Y3A2X3RibCAqdGJs LDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQ2NF90IGZsdXNoX3RpbWVzdGFtcCw8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX21idWYgKipvdXQsPGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDE2X3QgbmJfb3V0KTs8YnI+DQorPGJyPg0KKy8q Kjxicj4NCisgKiBUaGlzIGZ1bmN0aW9uIHJldHVybnMgdGhlIG51bWJlciBvZiB0aGUgcGFja2V0 cyBpbiBhIFRDUC9JUHY2PGJyPg0KKyAqIHJlYXNzZW1ibHkgdGFibGUuPGJyPg0KKyAqPGJyPg0K KyAqIEBwYXJhbSB0Ymw8YnI+DQorICrCoCBUQ1AvSVB2NiByZWFzc2VtYmx5IHRhYmxlIHBvaW50 ZXI8YnI+DQorICo8YnI+DQorICogQHJldHVybjxicj4NCisgKsKgIFRoZSBudW1iZXIgb2YgcGFj a2V0cyBpbiB0aGUgdGFibGU8YnI+DQorICovPGJyPg0KK3VpbnQzMl90IGdyb190Y3A2X3RibF9w a3RfY291bnQodm9pZCAqdGJsKTs8YnI+DQorPGJyPg0KKy8qPGJyPg0KKyAqIENoZWNrIGlmIHR3 byBUQ1AvSVB2NiBwYWNrZXRzIGJlbG9uZyB0byB0aGUgc2FtZSBmbG93Ljxicj4NCisgKi88YnI+ DQorc3RhdGljIGlubGluZSBpbnQ8YnI+DQoraXNfc2FtZV90Y3A2X2Zsb3coc3RydWN0IHRjcDZf Zmxvd19rZXkgKmsxLCBzdHJ1Y3QgdGNwNl9mbG93X2tleSAqazIpPGJyPg0KK3s8YnI+DQorwqAg wqAgwqAgwqBydGVfYmUzMl90IHZ0Y19mbG93X2RpZmY7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDC oGlmIChtZW1jbXAoJmFtcDtrMS0mZ3Q7c3JjX2FkZHIsICZhbXA7azItJmd0O3NyY19hZGRyLCAx NikpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIDA7PGJyPg0KK8KgIMKgIMKg IMKgaWYgKG1lbWNtcCgmYW1wO2sxLSZndDtkc3RfYWRkciwgJmFtcDtrMi0mZ3Q7ZHN0X2FkZHIs IDE2KSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gMDs8YnI+DQorwqAgwqAg wqAgwqAvKjxicj4NCivCoCDCoCDCoCDCoCAqIElQIHZlcnNpb24gKDQpIFRyYWZmaWMgQ2xhc3Mg KDgpIEZsb3cgTGFiZWwgKDIwKTxicj4NCivCoCDCoCDCoCDCoCAqIEFsbCBmaWVsZHMgZXhjZXB0 IFRyYWZmaWMgY2xhc3Mgc2hvdWxkIGJlIHNhbWU8YnI+DQorwqAgwqAgwqAgwqAgKi88YnI+DQor wqAgwqAgwqAgwqB2dGNfZmxvd19kaWZmID0gKGsxLSZndDt2dGNfZmxvdyBeIGsyLSZndDt2dGNf Zmxvdyk7PGJyPg0KK8KgIMKgIMKgIMKgaWYgKHZ0Y19mbG93X2RpZmYgJmFtcDsgaHRvbmwoMHhG MDBGRkZGRikpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIDA7PGJyPg0KKzxi cj4NCivCoCDCoCDCoCDCoHJldHVybiBpc19zYW1lX2NvbW1vbl90Y3Bfa2V5KCZhbXA7azEtJmd0 O2Ntbl9rZXksICZhbXA7azItJmd0O2Ntbl9rZXkpOzxicj4NCit9PGJyPg0KKzxicj4NCisjZW5k aWY8YnI+DQpkaWZmIC0tZ2l0IGEvbGliL2dyby9ncm9fdGNwX2ludGVybmFsLmggYi9saWIvZ3Jv L2dyb190Y3BfaW50ZXJuYWwuaDxicj4NCm5ldyBmaWxlIG1vZGUgMTAwNjQ0PGJyPg0KaW5kZXgg MDAwMDAwMDAwMC4uY2M4NGFiZWFlYjxicj4NCi0tLSAvZGV2L251bGw8YnI+DQorKysgYi9saWIv Z3JvL2dyb190Y3BfaW50ZXJuYWwuaDxicj4NCkBAIC0wLDAgKzEsMTI4IEBAPGJyPg0KKzxicj4N CisvKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQlNELTMtQ2xhdXNlPGJyPg0KKyAqIENvcHly aWdodChjKSAyMDIzIEludGVsIENvcnBvcmF0aW9uPGJyPg0KKyAqLzxicj4NCis8YnI+DQorI2lm bmRlZiBfR1JPX1RDUF9JTlRFUk5BTF9IXzxicj4NCisjZGVmaW5lIF9HUk9fVENQX0lOVEVSTkFM X0hfPGJyPg0KKzxicj4NCitzdGF0aWMgaW5saW5lIHVpbnQzMl90PGJyPg0KK2ZpbmRfYW5fZW1w dHlfaXRlbShzdHJ1Y3QgZ3JvX3RjcF9pdGVtICppdGVtcyw8YnI+DQorwqAgwqAgwqAgwqB1aW50 MzJfdCBtYXhfaXRlbV9udW0pPGJyPg0KK3s8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBpOzxi cj4NCis8YnI+DQorwqAgwqAgwqAgwqBmb3IgKGkgPSAwOyBpICZsdDsgbWF4X2l0ZW1fbnVtOyBp KyspPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGl0ZW1zW2ldLmZpcnN0c2VnID09 IE5VTEwpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIGk7 PGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIElOVkFMSURfQVJSQVlfSU5ERVg7PGJyPg0KK308YnI+ DQorPGJyPg0KK3N0YXRpYyBpbmxpbmUgdWludDMyX3Q8YnI+DQoraW5zZXJ0X25ld190Y3BfaXRl bShzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzdHJ1 Y3QgZ3JvX3RjcF9pdGVtICppdGVtcyw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50 MzJfdCAqaXRlbV9udW0sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDMyX3QgbWF4 X2l0ZW1fbnVtLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQ2NF90IHN0YXJ0X3Rp bWUsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDMyX3QgcHJldl9pZHgsPGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDMyX3Qgc2VudF9zZXEsPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgdWludDE2X3QgaXBfaWQsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgdWludDhfdCBpc19hdG9taWMpPGJyPg0KK3s8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBp dGVtX2lkeDs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgaXRlbV9pZHggPSBmaW5kX2FuX2VtcHR5 X2l0ZW0oaXRlbXMsIG1heF9pdGVtX251bSk7PGJyPg0KK8KgIMKgIMKgIMKgaWYgKGl0ZW1faWR4 ID09IElOVkFMSURfQVJSQVlfSU5ERVgpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0 dXJuIElOVkFMSURfQVJSQVlfSU5ERVg7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGl0ZW1zW2l0 ZW1faWR4XS5maXJzdHNlZyA9IHBrdDs8YnI+DQorwqAgwqAgwqAgwqBpdGVtc1tpdGVtX2lkeF0u bGFzdHNlZyA9IHJ0ZV9wa3RtYnVmX2xhc3RzZWcocGt0KTs8YnI+DQorwqAgwqAgwqAgwqBpdGVt c1tpdGVtX2lkeF0uc3RhcnRfdGltZSA9IHN0YXJ0X3RpbWU7PGJyPg0KK8KgIMKgIMKgIMKgaXRl bXNbaXRlbV9pZHhdLm5leHRfcGt0X2lkeCA9IElOVkFMSURfQVJSQVlfSU5ERVg7PGJyPg0KK8Kg IMKgIMKgIMKgaXRlbXNbaXRlbV9pZHhdLnNlbnRfc2VxID0gc2VudF9zZXE7PGJyPg0KK8KgIMKg IMKgIMKgaXRlbXNbaXRlbV9pZHhdLmwzLmlwX2lkID0gaXBfaWQ7PGJyPg0KK8KgIMKgIMKgIMKg aXRlbXNbaXRlbV9pZHhdLm5iX21lcmdlZCA9IDE7PGJyPg0KK8KgIMKgIMKgIMKgaXRlbXNbaXRl bV9pZHhdLmlzX2F0b21pYyA9IGlzX2F0b21pYzs8YnI+DQorwqAgwqAgwqAgwqAoKml0ZW1fbnVt KSArPSAxOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAvKiBpZiB0aGUgcHJldmlvdXMgcGFja2V0 IGV4aXN0cywgY2hhaW4gdGhlbSB0b2dldGhlci4gKi88YnI+DQorwqAgwqAgwqAgwqBpZiAocHJl dl9pZHggIT0gSU5WQUxJRF9BUlJBWV9JTkRFWCkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoGl0ZW1zW2l0ZW1faWR4XS5uZXh0X3BrdF9pZHggPTxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW1zW3ByZXZfaWR4XS5uZXh0X3BrdF9pZHg7PGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgaXRlbXNbcHJldl9pZHhdLm5leHRfcGt0X2lkeCA9IGl0ZW1f aWR4Ozxicj4NCivCoCDCoCDCoCDCoH08YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIGl0 ZW1faWR4Ozxicj4NCit9PGJyPg0KKzxicj4NCitzdGF0aWMgaW5saW5lIHVpbnQzMl90PGJyPg0K K2RlbGV0ZV90Y3BfaXRlbShzdHJ1Y3QgZ3JvX3RjcF9pdGVtICppdGVtcywgdWludDMyX3QgaXRl bV9pZHgsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDMyX3QgKml0ZW1fbnVtLDxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90IHByZXZfaXRlbV9pZHgpPGJyPg0K K3s8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBuZXh0X2lkeCA9IGl0ZW1zW2l0ZW1faWR4XS5u ZXh0X3BrdF9pZHg7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoC8qIE5VTEwgaW5kaWNhdGVzIGFu IGVtcHR5IGl0ZW0gKi88YnI+DQorwqAgwqAgwqAgwqBpdGVtc1tpdGVtX2lkeF0uZmlyc3RzZWcg PSBOVUxMOzxicj4NCivCoCDCoCDCoCDCoCgqaXRlbV9udW0pIC09IDE7PGJyPg0KK8KgIMKgIMKg IMKgaWYgKHByZXZfaXRlbV9pZHggIT0gSU5WQUxJRF9BUlJBWV9JTkRFWCk8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBpdGVtc1twcmV2X2l0ZW1faWR4XS5uZXh0X3BrdF9pZHggPSBuZXh0 X2lkeDs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIG5leHRfaWR4Ozxicj4NCit9PGJy Pg0KKzxicj4NCitzdGF0aWMgaW5saW5lIGludDMyX3Q8YnI+DQorcHJvY2Vzc190Y3BfaXRlbShz dHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX3RjcF9oZHIg KnRjcF9oZHIsPGJyPg0KK8KgIMKgIMKgIMKgaW50MzJfdCB0Y3BfZGwsPGJyPg0KK8KgIMKgIMKg IMKgc3RydWN0IGdyb190Y3BfaXRlbSAqaXRlbXMsPGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3Qg aXRlbV9pZHgsPGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgKml0ZW1fbnVtLDxicj4NCivCoCDC oCDCoCDCoHVpbnQzMl90IG1heF9pdGVtX251bSw8YnI+DQorwqAgwqAgwqAgwqB1aW50MTZfdCBp cF9pZCw8YnI+DQorwqAgwqAgwqAgwqB1aW50OF90IGlzX2F0b21pYyw8YnI+DQorwqAgwqAgwqAg wqB1aW50NjRfdCBzdGFydF90aW1lKTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3Qg Y3VyX2lkeDs8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBwcmV2X2lkeDs8YnI+DQorwqAgwqAg wqAgwqBpbnQgY21wOzxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRfc2VxOzxicj4NCis8 YnI+DQorwqAgwqAgwqAgwqBzZW50X3NlcSA9IHJ0ZV9iZV90b19jcHVfMzIodGNwX2hkci0mZ3Q7 c2VudF9zZXEpOzxicj4NCivCoCDCoCDCoCDCoC8qPGJyPg0KK8KgIMKgIMKgIMKgICogQ2hlY2sg YWxsIHBhY2tldHMgaW4gdGhlIGZsb3cgYW5kIHRyeSB0byBmaW5kIGEgbmVpZ2hib3IgZm9yPGJy Pg0KK8KgIMKgIMKgIMKgICogdGhlIGlucHV0IHBhY2tldC48YnI+DQorwqAgwqAgwqAgwqAgKi88 YnI+DQorwqAgwqAgwqAgwqBjdXJfaWR4ID0gaXRlbV9pZHg7PGJyPg0KK8KgIMKgIMKgIMKgcHJl dl9pZHggPSBjdXJfaWR4Ozxicj4NCivCoCDCoCDCoCDCoGRvIHs8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBjbXAgPSBjaGVja19zZXFfb3B0aW9uKCZhbXA7aXRlbXNbY3VyX2lkeF0sIHRj cF9oZHIsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgc2VudF9zZXEsIGlwX2lkLCBwa3QtJmd0O2w0X2xlbiwgdGNwX2RsLCAwLDxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlzX2F0b21pYyk7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGNtcCkgezxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChtZXJnZV90d29fdGNwX3BhY2tldHMoJmFtcDtpdGVt c1tjdXJfaWR4XSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3QsIGNtcCwgc2VudF9zZXEsIGlwX2lk LCAwKSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqByZXR1cm4gMTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKjxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqIEZhaWwgdG8gbWVyZ2Ug dGhlIHR3byBwYWNrZXRzLCBhcyB0aGUgcGFja2V0PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgICogbGVuZ3RoIGlzIGdyZWF0ZXIgdGhhbiB0aGUgbWF4IHZhbHVlLiBT dG9yZTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqIHRoZSBwYWNr ZXQgaW50byB0aGUgZmxvdy48YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoaW5zZXJ0 X25ld190Y3BfaXRlbShwa3QsIGl0ZW1zLCBpdGVtX251bSwgbWF4X2l0ZW1fbnVtLDxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHN0YXJ0X3RpbWUsIGN1cl9pZHgsIHNlbnRfc2VxLCBpcF9pZCwgaXNfYXRv bWljKSA9PTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoElOVkFMSURfQVJSQVlfSU5ERVgpPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIC0xOzxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiAwOzxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwcmV2X2lkeCA9IGN1cl9p ZHg7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgY3VyX2lkeCA9IGl0ZW1zW2N1cl9pZHhd Lm5leHRfcGt0X2lkeDs8YnI+DQorwqAgwqAgwqAgwqB9IHdoaWxlIChjdXJfaWR4ICE9IElOVkFM SURfQVJSQVlfSU5ERVgpOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAvKiBGYWlsIHRvIGZpbmQg YSBuZWlnaGJvciwgc28gc3RvcmUgdGhlIHBhY2tldCBpbnRvIHRoZSBmbG93LiAqLzxicj4NCivC oCDCoCDCoCDCoGlmIChpbnNlcnRfbmV3X3RjcF9pdGVtKHBrdCwgaXRlbXMsIGl0ZW1fbnVtLCBt YXhfaXRlbV9udW0sIHN0YXJ0X3RpbWUsIHByZXZfaWR4LCBzZW50X3NlcSw8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpcF9pZCwgaXNfYXRvbWlj KSA9PSBJTlZBTElEX0FSUkFZX0lOREVYKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJl dHVybiAtMTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIDA7PGJyPg0KK308YnI+DQor I2VuZGlmPGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vZ3JvX3Z4bGFuX3RjcDQuYyBiL2xpYi9n cm8vZ3JvX3Z4bGFuX3RjcDQuYzxicj4NCmluZGV4IDNiZTRkZWI3YzcuLjZhYjcwMDE5MjIgMTAw NjQ0PGJyPg0KLS0tIGEvbGliL2dyby9ncm9fdnhsYW5fdGNwNC5jPGJyPg0KKysrIGIvbGliL2dy by9ncm9fdnhsYW5fdGNwNC5jPGJyPg0KQEAgLTExNiw3ICsxMTYsNyBAQCBpbnNlcnRfbmV3X2l0 ZW0oc3RydWN0IGdyb192eGxhbl90Y3A0X3RibCAqdGJsLDxicj4NCsKgIMKgIMKgIMKgIHRibC0m Z3Q7aXRlbXNbaXRlbV9pZHhdLmlubmVyX2l0ZW0uc3RhcnRfdGltZSA9IHN0YXJ0X3RpbWU7PGJy Pg0KwqAgwqAgwqAgwqAgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0uaW5uZXJfaXRlbS5uZXh0X3Br dF9pZHggPSBJTlZBTElEX0FSUkFZX0lOREVYOzxicj4NCsKgIMKgIMKgIMKgIHRibC0mZ3Q7aXRl bXNbaXRlbV9pZHhdLmlubmVyX2l0ZW0uc2VudF9zZXEgPSBzZW50X3NlcTs8YnI+DQotwqAgwqAg wqAgwqB0YmwtJmd0O2l0ZW1zW2l0ZW1faWR4XS5pbm5lcl9pdGVtLmlwX2lkID0gaXBfaWQ7PGJy Pg0KK8KgIMKgIMKgIMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0uaW5uZXJfaXRlbS5sMy5pcF9p ZCA9IGlwX2lkOzxicj4NCsKgIMKgIMKgIMKgIHRibC0mZ3Q7aXRlbXNbaXRlbV9pZHhdLmlubmVy X2l0ZW0ubmJfbWVyZ2VkID0gMTs8YnI+DQrCoCDCoCDCoCDCoCB0YmwtJmd0O2l0ZW1zW2l0ZW1f aWR4XS5pbm5lcl9pdGVtLmlzX2F0b21pYyA9IGlzX2F0b21pYzs8YnI+DQrCoCDCoCDCoCDCoCB0 YmwtJmd0O2l0ZW1zW2l0ZW1faWR4XS5vdXRlcl9pcF9pZCA9IG91dGVyX2lwX2lkOzxicj4NCkBA IC0xNjMsMTUgKzE2Myw5IEBAIGluc2VydF9uZXdfZmxvdyhzdHJ1Y3QgZ3JvX3Z4bGFuX3RjcDRf dGJsICp0YmwsPGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgZHN0ID0gJmFtcDsodGJsLSZndDtmbG93 c1tmbG93X2lkeF0ua2V5KTs8YnI+DQo8YnI+DQotwqAgwqAgwqAgwqBydGVfZXRoZXJfYWRkcl9j b3B5KCZhbXA7KHNyYy0mZ3Q7aW5uZXJfa2V5LmV0aF9zYWRkciksPGJyPg0KLcKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgJmFtcDsoZHN0LSZndDtpbm5lcl9rZXkuZXRoX3NhZGRy KSk7PGJyPg0KLcKgIMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJfY29weSgmYW1wOyhzcmMtJmd0O2lu bmVyX2tleS5ldGhfZGFkZHIpLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCZhbXA7KGRzdC0mZ3Q7aW5uZXJfa2V5LmV0aF9kYWRkcikpOzxicj4NCivCoCDCoCDCoCDC oEFTU0lHTl9DT01NT05fVENQX0tFWSgoJmFtcDsoc3JjLSZndDtpbm5lcl9rZXkuY21uX2tleSkp LCAoJmFtcDsoZHN0LSZndDtpbm5lcl9rZXkuY21uX2tleSkpKTs8YnI+DQrCoCDCoCDCoCDCoCBk c3QtJmd0O2lubmVyX2tleS5pcF9zcmNfYWRkciA9IHNyYy0mZ3Q7aW5uZXJfa2V5LmlwX3NyY19h ZGRyOzxicj4NCsKgIMKgIMKgIMKgIGRzdC0mZ3Q7aW5uZXJfa2V5LmlwX2RzdF9hZGRyID0gc3Jj LSZndDtpbm5lcl9rZXkuaXBfZHN0X2FkZHI7PGJyPg0KLcKgIMKgIMKgIMKgZHN0LSZndDtpbm5l cl9rZXkucmVjdl9hY2sgPSBzcmMtJmd0O2lubmVyX2tleS5yZWN2X2Fjazs8YnI+DQotwqAgwqAg wqAgwqBkc3QtJmd0O2lubmVyX2tleS5zcmNfcG9ydCA9IHNyYy0mZ3Q7aW5uZXJfa2V5LnNyY19w b3J0Ozxicj4NCi3CoCDCoCDCoCDCoGRzdC0mZ3Q7aW5uZXJfa2V5LmRzdF9wb3J0ID0gc3JjLSZn dDtpbm5lcl9rZXkuZHN0X3BvcnQ7PGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgZHN0LSZndDt2eGxh bl9oZHIudnhfZmxhZ3MgPSBzcmMtJmd0O3Z4bGFuX2hkci52eF9mbGFnczs8YnI+DQrCoCDCoCDC oCDCoCBkc3QtJmd0O3Z4bGFuX2hkci52eF92bmkgPSBzcmMtJmd0O3Z4bGFuX2hkci52eF92bmk7 PGJyPg0KQEAgLTI0OCw3ICsyNDIsNyBAQCBtZXJnZV90d29fdnhsYW5fdGNwNF9wYWNrZXRzKHN0 cnVjdCBncm9fdnhsYW5fdGNwNF9pdGVtICppdGVtLDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIHVpbnQxNl90IG91dGVyX2lwX2lkLDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHVp bnQxNl90IGlwX2lkKTxicj4NCsKgezxicj4NCi3CoCDCoCDCoCDCoGlmIChtZXJnZV90d29fdGNw NF9wYWNrZXRzKCZhbXA7aXRlbS0mZ3Q7aW5uZXJfaXRlbSwgcGt0LCBjbXAsIHNlbnRfc2VxLDxi cj4NCivCoCDCoCDCoCDCoGlmIChtZXJnZV90d29fdGNwX3BhY2tldHMoJmFtcDtpdGVtLSZndDtp bm5lcl9pdGVtLCBwa3QsIGNtcCwgc2VudF9zZXEsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaXBfaWQsIHBrdC0mZ3Q7b3V0ZXJfbDJfbGVuICs8 YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBwa3Qt Jmd0O291dGVyX2wzX2xlbikpIHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAvKiBVcGRh dGUgdGhlIG91dGVyIElQdjQgSUQgdG8gdGhlIGxhcmdlIHZhbHVlLiAqLzxicj4NCkBAIC0zNTcs MTMgKzM1MSwxMyBAQCBncm9fdnhsYW5fdGNwNF9yZWFzc2VtYmxlKHN0cnVjdCBydGVfbWJ1ZiAq cGt0LDxicj4NCjxicj4NCsKgIMKgIMKgIMKgIHNlbnRfc2VxID0gcnRlX2JlX3RvX2NwdV8zMih0 Y3BfaGRyLSZndDtzZW50X3NlcSk7PGJyPg0KPGJyPg0KLcKgIMKgIMKgIMKgcnRlX2V0aGVyX2Fk ZHJfY29weSgmYW1wOyhldGhfaGRyLSZndDtzcmNfYWRkciksICZhbXA7KGtleS5pbm5lcl9rZXku ZXRoX3NhZGRyKSk7PGJyPg0KLcKgIMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJfY29weSgmYW1wOyhl dGhfaGRyLSZndDtkc3RfYWRkciksICZhbXA7KGtleS5pbm5lcl9rZXkuZXRoX2RhZGRyKSk7PGJy Pg0KK8KgIMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJfY29weSgmYW1wOyhldGhfaGRyLSZndDtzcmNf YWRkciksICZhbXA7KGtleS5pbm5lcl9rZXkuY21uX2tleS5ldGhfc2FkZHIpKTs8YnI+DQorwqAg wqAgwqAgwqBydGVfZXRoZXJfYWRkcl9jb3B5KCZhbXA7KGV0aF9oZHItJmd0O2RzdF9hZGRyKSwg JmFtcDsoa2V5LmlubmVyX2tleS5jbW5fa2V5LmV0aF9kYWRkcikpOzxicj4NCsKgIMKgIMKgIMKg IGtleS5pbm5lcl9rZXkuaXBfc3JjX2FkZHIgPSBpcHY0X2hkci0mZ3Q7c3JjX2FkZHI7PGJyPg0K wqAgwqAgwqAgwqAga2V5LmlubmVyX2tleS5pcF9kc3RfYWRkciA9IGlwdjRfaGRyLSZndDtkc3Rf YWRkcjs8YnI+DQotwqAgwqAgwqAgwqBrZXkuaW5uZXJfa2V5LnJlY3ZfYWNrID0gdGNwX2hkci0m Z3Q7cmVjdl9hY2s7PGJyPg0KLcKgIMKgIMKgIMKga2V5LmlubmVyX2tleS5zcmNfcG9ydCA9IHRj cF9oZHItJmd0O3NyY19wb3J0Ozxicj4NCi3CoCDCoCDCoCDCoGtleS5pbm5lcl9rZXkuZHN0X3Bv cnQgPSB0Y3BfaGRyLSZndDtkc3RfcG9ydDs8YnI+DQorwqAgwqAgwqAgwqBrZXkuaW5uZXJfa2V5 LmNtbl9rZXkucmVjdl9hY2sgPSB0Y3BfaGRyLSZndDtyZWN2X2Fjazs8YnI+DQorwqAgwqAgwqAg wqBrZXkuaW5uZXJfa2V5LmNtbl9rZXkuc3JjX3BvcnQgPSB0Y3BfaGRyLSZndDtzcmNfcG9ydDs8 YnI+DQorwqAgwqAgwqAgwqBrZXkuaW5uZXJfa2V5LmNtbl9rZXkuZHN0X3BvcnQgPSB0Y3BfaGRy LSZndDtkc3RfcG9ydDs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCBrZXkudnhsYW5faGRyLnZ4X2Zs YWdzID0gdnhsYW5faGRyLSZndDt2eF9mbGFnczs8YnI+DQrCoCDCoCDCoCDCoCBrZXkudnhsYW5f aGRyLnZ4X3ZuaSA9IHZ4bGFuX2hkci0mZ3Q7dnhfdm5pOzxicj4NCmRpZmYgLS1naXQgYS9saWIv Z3JvL2dyb192eGxhbl90Y3A0LmggYi9saWIvZ3JvL2dyb192eGxhbl90Y3A0Lmg8YnI+DQppbmRl eCA3ODMyOTQyYTY4Li42NjJkYjAxYTg4IDEwMDY0NDxicj4NCi0tLSBhL2xpYi9ncm8vZ3JvX3Z4 bGFuX3RjcDQuaDxicj4NCisrKyBiL2xpYi9ncm8vZ3JvX3Z4bGFuX3RjcDQuaDxicj4NCkBAIC0z Niw3ICszNiw3IEBAIHN0cnVjdCBncm9fdnhsYW5fdGNwNF9mbG93IHs8YnI+DQrCoH07PGJyPg0K PGJyPg0KwqBzdHJ1Y3QgZ3JvX3Z4bGFuX3RjcDRfaXRlbSB7PGJyPg0KLcKgIMKgIMKgIMKgc3Ry dWN0IGdyb190Y3A0X2l0ZW0gaW5uZXJfaXRlbTs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgZ3Jv X3RjcF9pdGVtIGlubmVyX2l0ZW07PGJyPg0KwqAgwqAgwqAgwqAgLyogSVB2NCBJRCBpbiB0aGUg b3V0ZXIgSVB2NCBoZWFkZXIgKi88YnI+DQrCoCDCoCDCoCDCoCB1aW50MTZfdCBvdXRlcl9pcF9p ZDs8YnI+DQrCoCDCoCDCoCDCoCAvKiBJbmRpY2F0ZSBpZiBvdXRlciBJUHY0IElEIGNhbiBiZSBp Z25vcmVkICovPGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vbWVzb24uYnVpbGQgYi9saWIvZ3Jv L21lc29uLmJ1aWxkPGJyPg0KaW5kZXggZTRmYTI5NThiZC4uZGJjZTA1MjIwZCAxMDA2NDQ8YnI+ DQotLS0gYS9saWIvZ3JvL21lc29uLmJ1aWxkPGJyPg0KKysrIGIvbGliL2dyby9tZXNvbi5idWls ZDxicj4NCkBAIC00LDYgKzQsNyBAQDxicj4NCsKgc291cmNlcyA9IGZpbGVzKDxicj4NCsKgIMKg IMKgIMKgIMKgJiMzOTtydGVfZ3JvLmMmIzM5Oyw8YnI+DQrCoCDCoCDCoCDCoCDCoCYjMzk7Z3Jv X3RjcDQuYyYjMzk7LDxicj4NCivCoCDCoCDCoCDCoCAmIzM5O2dyb190Y3A2LmMmIzM5Oyw8YnI+ DQrCoCDCoCDCoCDCoCDCoCYjMzk7Z3JvX3VkcDQuYyYjMzk7LDxicj4NCsKgIMKgIMKgIMKgIMKg JiMzOTtncm9fdnhsYW5fdGNwNC5jJiMzOTssPGJyPg0KwqAgwqAgwqAgwqAgwqAmIzM5O2dyb192 eGxhbl91ZHA0LmMmIzM5Oyw8YnI+DQpkaWZmIC0tZ2l0IGEvbGliL2dyby9ydGVfZ3JvLmMgYi9s aWIvZ3JvL3J0ZV9ncm8uYzxicj4NCmluZGV4IGUzNTM5OWZkNDIuLmQ4MjRlZWJkOTMgMTAwNjQ0 PGJyPg0KLS0tIGEvbGliL2dyby9ydGVfZ3JvLmM8YnI+DQorKysgYi9saWIvZ3JvL3J0ZV9ncm8u Yzxicj4NCkBAIC04LDYgKzgsNyBAQDxicj4NCjxicj4NCsKgI2luY2x1ZGUgJnF1b3Q7cnRlX2dy by5oJnF1b3Q7PGJyPg0KwqAjaW5jbHVkZSAmcXVvdDtncm9fdGNwNC5oJnF1b3Q7PGJyPg0KKyNp bmNsdWRlICZxdW90O2dyb190Y3A2LmgmcXVvdDs8YnI+DQrCoCNpbmNsdWRlICZxdW90O2dyb191 ZHA0LmgmcXVvdDs8YnI+DQrCoCNpbmNsdWRlICZxdW90O2dyb192eGxhbl90Y3A0LmgmcXVvdDs8 YnI+DQrCoCNpbmNsdWRlICZxdW90O2dyb192eGxhbl91ZHA0LmgmcXVvdDs8YnI+DQpAQCAtMjAs MTQgKzIxLDE2IEBAIHR5cGVkZWYgdWludDMyX3QgKCpncm9fdGJsX3BrdF9jb3VudF9mbikodm9p ZCAqdGJsKTs8YnI+DQo8YnI+DQrCoHN0YXRpYyBncm9fdGJsX2NyZWF0ZV9mbiB0YmxfY3JlYXRl X2ZuW1JURV9HUk9fVFlQRV9NQVhfTlVNXSA9IHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCBncm9fdGNwNF90YmxfY3JlYXRlLCBncm9fdnhsYW5fdGNwNF90YmxfY3JlYXRlLDxicj4NCi3C oCDCoCDCoCDCoCDCoCDCoCDCoCDCoGdyb191ZHA0X3RibF9jcmVhdGUsIGdyb192eGxhbl91ZHA0 X3RibF9jcmVhdGUsIE5VTEx9Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGdyb191ZHA0 X3RibF9jcmVhdGUsIGdyb192eGxhbl91ZHA0X3RibF9jcmVhdGUsIGdyb190Y3A2X3RibF9jcmVh dGUsIE5VTEx9Ozxicj4NCsKgc3RhdGljIGdyb190YmxfZGVzdHJveV9mbiB0YmxfZGVzdHJveV9m bltSVEVfR1JPX1RZUEVfTUFYX05VTV0gPSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgZ3JvX3RjcDRfdGJsX2Rlc3Ryb3ksIGdyb192eGxhbl90Y3A0X3RibF9kZXN0 cm95LDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGdyb191ZHA0X3Ri bF9kZXN0cm95LCBncm9fdnhsYW5fdWRwNF90YmxfZGVzdHJveSw8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBncm9fdGNwNl90YmxfZGVzdHJveSw8YnI+DQrCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBOVUxMfTs8YnI+DQrCoHN0YXRpYyBncm9fdGJs X3BrdF9jb3VudF9mbiB0YmxfcGt0X2NvdW50X2ZuW1JURV9HUk9fVFlQRV9NQVhfTlVNXSA9IHs8 YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBncm9fdGNwNF90YmxfcGt0 X2NvdW50LCBncm9fdnhsYW5fdGNwNF90YmxfcGt0X2NvdW50LDxicj4NCsKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIGdyb191ZHA0X3RibF9wa3RfY291bnQsIGdyb192eGxhbl91 ZHA0X3RibF9wa3RfY291bnQsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgZ3JvX3RjcDZfdGJsX3BrdF9jb3VudCw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCBOVUxMfTs8YnI+DQo8YnI+DQrCoCNkZWZpbmUgSVNfSVBWNF9UQ1BfUEtUKHB0 eXBlKSAoUlRFX0VUSF9JU19JUFY0X0hEUihwdHlwZSkgJmFtcDsmYW1wOyBcPGJyPg0KQEAgLTM1 LDYgKzM4LDEyIEBAIHN0YXRpYyBncm9fdGJsX3BrdF9jb3VudF9mbiB0YmxfcGt0X2NvdW50X2Zu W1JURV9HUk9fVFlQRV9NQVhfTlVNXSA9IHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAo KHB0eXBlICZhbXA7IFJURV9QVFlQRV9MNF9GUkFHKSAhPSBSVEVfUFRZUEVfTDRfRlJBRykgJmFt cDsmYW1wOyBcPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKFJURV9FVEhfSVNfVFVOTkVM X1BLVChwdHlwZSkgPT0gMCkpPGJyPg0KPGJyPg0KKy8qIEdSTyB3aXRoIGV4dGVuc2lvbiBoZWFk ZXJzIGlzIG5vdCBzdXBwb3J0ZWQgKi88YnI+DQorI2RlZmluZSBJU19JUFY2X1RDUF9QS1QocHR5 cGUpIChSVEVfRVRIX0lTX0lQVjZfSERSKHB0eXBlKSAmYW1wOyZhbXA7IFw8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAoKHB0eXBlICZhbXA7IFJURV9QVFlQRV9MNF9UQ1ApID09IFJURV9Q VFlQRV9MNF9UQ1ApICZhbXA7JmFtcDsgXDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCgo cHR5cGUgJmFtcDsgUlRFX1BUWVBFX0w0X0ZSQUcpICE9IFJURV9QVFlQRV9MNF9GUkFHKSAmYW1w OyZhbXA7IFw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAoUlRFX0VUSF9JU19UVU5ORUxf UEtUKHB0eXBlKSA9PSAwKSk8YnI+DQorPGJyPg0KwqAjZGVmaW5lIElTX0lQVjRfVURQX1BLVChw dHlwZSkgKFJURV9FVEhfSVNfSVBWNF9IRFIocHR5cGUpICZhbXA7JmFtcDsgXDxicj4NCsKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgICgocHR5cGUgJmFtcDsgUlRFX1BUWVBFX0w0X1VEUCkgPT0gUlRF X1BUWVBFX0w0X1VEUCkgJmFtcDsmYW1wOyBcPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg KFJURV9FVEhfSVNfVFVOTkVMX1BLVChwdHlwZSkgPT0gMCkpPGJyPg0KQEAgLTE0Nyw3ICsxNTYs MTEgQEAgcnRlX2dyb19yZWFzc2VtYmxlX2J1cnN0KHN0cnVjdCBydGVfbWJ1ZiAqKnBrdHMsPGJy Pg0KwqAgwqAgwqAgwqAgLyogYWxsb2NhdGUgYSByZWFzc2VtYmx5IHRhYmxlIGZvciBUQ1AvSVB2 NCBHUk8gKi88YnI+DQrCoCDCoCDCoCDCoCBzdHJ1Y3QgZ3JvX3RjcDRfdGJsIHRjcF90Ymw7PGJy Pg0KwqAgwqAgwqAgwqAgc3RydWN0IGdyb190Y3A0X2Zsb3cgdGNwX2Zsb3dzW1JURV9HUk9fTUFY X0JVUlNUX0lURU1fTlVNXTs8YnI+DQotwqAgwqAgwqAgwqBzdHJ1Y3QgZ3JvX3RjcDRfaXRlbSB0 Y3BfaXRlbXNbUlRFX0dST19NQVhfQlVSU1RfSVRFTV9OVU1dID0ge3swfSB9Ozxicj4NCivCoCDC oCDCoCDCoHN0cnVjdCBncm9fdGNwX2l0ZW0gdGNwX2l0ZW1zW1JURV9HUk9fTUFYX0JVUlNUX0lU RU1fTlVNXSA9IHt7MH0gfTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IGdyb190Y3A2 X3RibCB0Y3A2X3RibDs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgZ3JvX3RjcDZfZmxvdyB0Y3A2 X2Zsb3dzW1JURV9HUk9fTUFYX0JVUlNUX0lURU1fTlVNXTs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1 Y3QgZ3JvX3RjcF9pdGVtIHRjcDZfaXRlbXNbUlRFX0dST19NQVhfQlVSU1RfSVRFTV9OVU1dID0g e3swfSB9Ozxicj4NCjxicj4NCsKgIMKgIMKgIMKgIC8qIGFsbG9jYXRlIGEgcmVhc3NlbWJseSB0 YWJsZSBmb3IgVURQL0lQdjQgR1JPICovPGJyPg0KwqAgwqAgwqAgwqAgc3RydWN0IGdyb191ZHA0 X3RibCB1ZHBfdGJsOzxicj4NCkBAIC0xNzEsMTAgKzE4NCwxMCBAQCBydGVfZ3JvX3JlYXNzZW1i bGVfYnVyc3Qoc3RydWN0IHJ0ZV9tYnVmICoqcGt0cyw8YnI+DQrCoCDCoCDCoCDCoCBpbnQzMl90 IHJldDs8YnI+DQrCoCDCoCDCoCDCoCB1aW50MTZfdCBpLCB1bnByb2Nlc3NfbnVtID0gMCwgbmJf YWZ0ZXJfZ3JvID0gbmJfcGt0czs8YnI+DQrCoCDCoCDCoCDCoCB1aW50OF90IGRvX3RjcDRfZ3Jv ID0gMCwgZG9fdnhsYW5fdGNwX2dybyA9IDAsIGRvX3VkcDRfZ3JvID0gMCw8YnI+DQotwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBkb192eGxhbl91ZHBfZ3JvID0gMDs8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBkb192eGxhbl91ZHBfZ3JvID0gMCwgZG9fdGNwNl9ncm8gPSAwOzxicj4NCjxi cj4NCsKgIMKgIMKgIMKgIGlmICh1bmxpa2VseSgocGFyYW0tJmd0O2dyb190eXBlcyAmYW1wOyAo UlRFX0dST19JUFY0X1ZYTEFOX1RDUF9JUFY0IHw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBSVEVfR1JPX1RDUF9JUFY0IHw8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBSVEVfR1JPX1RDUF9JUFY0IHwgUlRFX0dST19UQ1BfSVBWNiB8PGJyPg0KwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgUlRF X0dST19JUFY0X1ZYTEFOX1VEUF9JUFY0IHw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBSVEVfR1JPX1VEUF9JUFY0KSkgPT0g MCkpPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuIG5iX3BrdHM7PGJyPg0KQEAg LTIzNiw2ICsyNDksMTggQEAgcnRlX2dyb19yZWFzc2VtYmxlX2J1cnN0KHN0cnVjdCBydGVfbWJ1 ZiAqKnBrdHMsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZG9fdWRwNF9ncm8gPSAxOzxi cj4NCsKgIMKgIMKgIMKgIH08YnI+DQo8YnI+DQorwqAgwqAgwqAgwqBpZiAocGFyYW0tJmd0O2dy b190eXBlcyAmYW1wOyBSVEVfR1JPX1RDUF9JUFY2KSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgZm9yIChpID0gMDsgaSAmbHQ7IGl0ZW1fbnVtOyBpKyspPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGNwNl9mbG93c1tpXS5zdGFydF9pbmRleCA9IElOVkFM SURfQVJSQVlfSU5ERVg7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRjcDZf dGJsLmZsb3dzID0gdGNwNl9mbG93czs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0Y3A2 X3RibC5pdGVtcyA9IHRjcDZfaXRlbXM7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGNw Nl90YmwuZmxvd19udW0gPSAwOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRjcDZfdGJs Lml0ZW1fbnVtID0gMDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0Y3A2X3RibC5tYXhf Zmxvd19udW0gPSBpdGVtX251bTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0Y3A2X3Ri bC5tYXhfaXRlbV9udW0gPSBpdGVtX251bTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBk b190Y3A2X2dybyA9IDE7PGJyPg0KK8KgIMKgIMKgIMKgfTxicj4NCjxicj4NCsKgIMKgIMKgIMKg IGZvciAoaSA9IDA7IGkgJmx0OyBuYl9wa3RzOyBpKyspIHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCAvKjxicj4NCkBAIC0yNzYsNiArMzAxLDE0IEBAIHJ0ZV9ncm9fcmVhc3NlbWJsZV9i dXJzdChzdHJ1Y3QgcnRlX21idWYgKipwa3RzLDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIG5iX2FmdGVyX2dyby0tOzxicj4NCsKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGVsc2UgaWYgKHJldCAmbHQ7IDApPGJyPg0KwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdW5wcm9jZXNzX3BrdHNb dW5wcm9jZXNzX251bSsrXSA9IHBrdHNbaV07PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg fSBlbHNlIGlmIChJU19JUFY2X1RDUF9QS1QocGt0c1tpXS0mZ3Q7cGFja2V0X3R5cGUpICZhbXA7 JmFtcDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBkb190Y3A2X2dybykgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oHJldCA9IGdyb190Y3A2X3JlYXNzZW1ibGUocGt0c1tpXSwgJmFtcDt0Y3A2X3RibCwgMCk7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKHJldCAmZ3Q7IDApPGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyogbWVy Z2Ugc3VjY2Vzc2Z1bGx5ICovPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgbmJfYWZ0ZXJfZ3JvLS07PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgZWxzZSBpZiAocmV0ICZsdDsgMCk8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1bnByb2Nlc3NfcGt0c1t1bnByb2Nlc3Nf bnVtKytdID0gcGt0c1tpXTs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9IGVsc2U8YnI+ DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB1bnByb2Nlc3NfcGt0c1t1bnBy b2Nlc3NfbnVtKytdID0gcGt0c1tpXTs8YnI+DQrCoCDCoCDCoCDCoCB9PGJyPg0KQEAgLTI4Myw5 ICszMTYsMTcgQEAgcnRlX2dyb19yZWFzc2VtYmxlX2J1cnN0KHN0cnVjdCBydGVfbWJ1ZiAqKnBr dHMsPGJyPg0KwqAgwqAgwqAgwqAgaWYgKChuYl9hZnRlcl9ncm8gJmx0OyBuYl9wa3RzKTxicj4N CsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfHwgKHVucHJvY2Vzc19udW0gJmx0OyBuYl9wa3Rz KSkgezxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGkgPSAwOzxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoC8qIENvcHkgdW5wcm9jZXNzZWQgcGFja2V0cyAqLzxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoGlmICh1bnByb2Nlc3NfbnVtICZndDsgMCkgezxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoG1lbWNweSgmYW1wO3BrdHNbaV0sIHVucHJvY2Vz c19wa3RzLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoHNpemVvZihzdHJ1Y3QgcnRlX21idWYgKikgKjxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVucHJv Y2Vzc19udW0pOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGkgPSB1 bnByb2Nlc3NfbnVtOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH08YnI+DQorPGJyPg0K wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgLyogRmx1c2ggYWxsIHBhY2tldHMgZnJvbSB0aGUgdGFi bGVzICovPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKGRvX3Z4bGFuX3RjcF9ncm8p IHs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpID0gZ3JvX3Z4bGFu X3RjcDRfdGJsX3RpbWVvdXRfZmx1c2goJmFtcDt2eGxhbl90Y3BfdGJsLDxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGkgKz0gZ3JvX3Z4bGFuX3RjcDRfdGJsX3RpbWVv dXRfZmx1c2goJmFtcDt2eGxhbl90Y3BfdGJsLDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIDAsIHBrdHMsIG5iX3BrdHMpOzxi cj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIH08YnI+DQo8YnI+DQpAQCAtMzA0LDEzICszNDUs MTEgQEAgcnRlX2dyb19yZWFzc2VtYmxlX2J1cnN0KHN0cnVjdCBydGVfbWJ1ZiAqKnBrdHMsPGJy Pg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaSArPSBncm9fdWRwNF90Ymxf dGltZW91dF9mbHVzaCgmYW1wO3VkcF90YmwsIDAsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgJmFtcDtwa3RzW2ldLCBuYl9w a3RzIC0gaSk7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfTxicj4NCi3CoCDCoCDCoCDC oCDCoCDCoCDCoCDCoC8qIENvcHkgdW5wcm9jZXNzZWQgcGFja2V0cyAqLzxicj4NCi3CoCDCoCDC oCDCoCDCoCDCoCDCoCDCoGlmICh1bnByb2Nlc3NfbnVtICZndDsgMCkgezxicj4NCi3CoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoG1lbWNweSgmYW1wO3BrdHNbaV0sIHVucHJvY2Vz c19wa3RzLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoHNpemVvZihzdHJ1Y3QgcnRlX21idWYgKikgKjxicj4NCi3CoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVucHJv Y2Vzc19udW0pOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoZG9fdGNw Nl9ncm8pIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpICs9IGdy b190Y3A2X3RibF90aW1lb3V0X2ZsdXNoKCZhbXA7dGNwNl90YmwsIDAsPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgJmFtcDtw a3RzW2ldLCBuYl9wa3RzIC0gaSk7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfTxicj4N Ci3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoG5iX2FmdGVyX2dybyA9IGkgKyB1bnByb2Nlc3NfbnVt Ozxicj4NCsKgIMKgIMKgIMKgIH08YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCByZXR1cm4gbmJfYWZ0 ZXJfZ3JvOzxicj4NCkBAIC0zMjMsMTMgKzM2MiwxMyBAQCBydGVfZ3JvX3JlYXNzZW1ibGUoc3Ry dWN0IHJ0ZV9tYnVmICoqcGt0cyw8YnI+DQrCoHs8YnI+DQrCoCDCoCDCoCDCoCBzdHJ1Y3QgcnRl X21idWYgKnVucHJvY2Vzc19wa3RzW25iX3BrdHNdOzxicj4NCsKgIMKgIMKgIMKgIHN0cnVjdCBn cm9fY3R4ICpncm9fY3R4ID0gY3R4Ozxicj4NCi3CoCDCoCDCoCDCoHZvaWQgKnRjcF90YmwsICp1 ZHBfdGJsLCAqdnhsYW5fdGNwX3RibCwgKnZ4bGFuX3VkcF90Ymw7PGJyPg0KK8KgIMKgIMKgIMKg dm9pZCAqdGNwX3RibCwgKnVkcF90YmwsICp2eGxhbl90Y3BfdGJsLCAqdnhsYW5fdWRwX3RibCwg KnRjcDZfdGJsOzxicj4NCsKgIMKgIMKgIMKgIHVpbnQ2NF90IGN1cnJlbnRfdGltZTs8YnI+DQrC oCDCoCDCoCDCoCB1aW50MTZfdCBpLCB1bnByb2Nlc3NfbnVtID0gMDs8YnI+DQotwqAgwqAgwqAg wqB1aW50OF90IGRvX3RjcDRfZ3JvLCBkb192eGxhbl90Y3BfZ3JvLCBkb191ZHA0X2dybywgZG9f dnhsYW5fdWRwX2dybzs8YnI+DQorwqAgwqAgwqAgwqB1aW50OF90IGRvX3RjcDRfZ3JvLCBkb192 eGxhbl90Y3BfZ3JvLCBkb191ZHA0X2dybywgZG9fdnhsYW5fdWRwX2dybywgZG9fdGNwNl9ncm87 PGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgaWYgKHVubGlrZWx5KChncm9fY3R4LSZndDtncm9fdHlw ZXMgJmFtcDsgKFJURV9HUk9fSVBWNF9WWExBTl9UQ1BfSVBWNCB8PGJyPg0KLcKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgUlRFX0dST19U Q1BfSVBWNCB8PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgUlRFX0dST19UQ1BfSVBWNCB8IFJURV9HUk9fVENQX0lQVjYgfDxi cj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIFJURV9HUk9fSVBWNF9WWExBTl9VRFBfSVBWNCB8PGJyPg0KwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgUlRFX0dST19VRFBf SVBWNCkpID09IDApKTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHJldHVybiBuYl9wa3Rz Ozxicj4NCkBAIC0zMzgsNiArMzc3LDcgQEAgcnRlX2dyb19yZWFzc2VtYmxlKHN0cnVjdCBydGVf bWJ1ZiAqKnBrdHMsPGJyPg0KwqAgwqAgwqAgwqAgdnhsYW5fdGNwX3RibCA9IGdyb19jdHgtJmd0 O3RibHNbUlRFX0dST19JUFY0X1ZYTEFOX1RDUF9JUFY0X0lOREVYXTs8YnI+DQrCoCDCoCDCoCDC oCB1ZHBfdGJsID0gZ3JvX2N0eC0mZ3Q7dGJsc1tSVEVfR1JPX1VEUF9JUFY0X0lOREVYXTs8YnI+ DQrCoCDCoCDCoCDCoCB2eGxhbl91ZHBfdGJsID0gZ3JvX2N0eC0mZ3Q7dGJsc1tSVEVfR1JPX0lQ VjRfVlhMQU5fVURQX0lQVjRfSU5ERVhdOzxicj4NCivCoCDCoCDCoCDCoHRjcDZfdGJsID0gZ3Jv X2N0eC0mZ3Q7dGJsc1tSVEVfR1JPX1RDUF9JUFY2X0lOREVYXTs8YnI+DQo8YnI+DQrCoCDCoCDC oCDCoCBkb190Y3A0X2dybyA9IChncm9fY3R4LSZndDtncm9fdHlwZXMgJmFtcDsgUlRFX0dST19U Q1BfSVBWNCkgPT08YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBSVEVfR1JPX1RDUF9JUFY0 Ozxicj4NCkBAIC0zNDcsNiArMzg3LDcgQEAgcnRlX2dyb19yZWFzc2VtYmxlKHN0cnVjdCBydGVf bWJ1ZiAqKnBrdHMsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgUlRFX0dST19VRFBfSVBW NDs8YnI+DQrCoCDCoCDCoCDCoCBkb192eGxhbl91ZHBfZ3JvID0gKGdyb19jdHgtJmd0O2dyb190 eXBlcyAmYW1wOyBSVEVfR1JPX0lQVjRfVlhMQU5fVURQX0lQVjQpID09PGJyPg0KwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgUlRFX0dST19JUFY0X1ZYTEFOX1VEUF9JUFY0Ozxicj4NCivCoCDCoCDC oCDCoGRvX3RjcDZfZ3JvID0gKGdyb19jdHgtJmd0O2dyb190eXBlcyAmYW1wOyBSVEVfR1JPX1RD UF9JUFY2KSA9PSBSVEVfR1JPX1RDUF9JUFY2Ozxicj4NCjxicj4NCsKgIMKgIMKgIMKgIGN1cnJl bnRfdGltZSA9IHJ0ZV9yZHRzYygpOzxicj4NCjxicj4NCkBAIC0zNzEsNiArNDEyLDExIEBAIHJ0 ZV9ncm9fcmVhc3NlbWJsZShzdHJ1Y3QgcnRlX21idWYgKipwa3RzLDxicj4NCsKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChncm9fdWRwNF9yZWFzc2VtYmxlKHBrdHNbaV0s IHVkcF90YmwsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgY3VycmVudF90aW1lKSAmbHQ7IDApPGJyPg0K wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdW5wcm9jZXNz X3BrdHNbdW5wcm9jZXNzX251bSsrXSA9IHBrdHNbaV07PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgfSBlbHNlIGlmIChJU19JUFY2X1RDUF9QS1QocGt0c1tpXS0mZ3Q7cGFja2V0X3R5cGUp ICZhbXA7JmFtcDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBkb190Y3A2X2dybykgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoGlmIChncm9fdGNwNl9yZWFzc2VtYmxlKHBrdHNbaV0sIHRjcDZfdGJsLDxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoGN1cnJlbnRfdGltZSkgJmx0OyAwKTxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVucHJvY2Vzc19wa3RzW3VucHJvY2Vzc19u dW0rK10gPSBwa3RzW2ldOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIH0gZWxzZTxicj4N CsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHVucHJvY2Vzc19wa3RzW3VucHJv Y2Vzc19udW0rK10gPSBwa3RzW2ldOzxicj4NCsKgIMKgIMKgIMKgIH08YnI+DQpAQCAtNDI2LDYg KzQ3MiwxNSBAQCBydGVfZ3JvX3RpbWVvdXRfZmx1c2godm9pZCAqY3R4LDxicj4NCsKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGdyb19jdHgtJmd0O3RibHNb UlRFX0dST19VRFBfSVBWNF9JTkRFWF0sPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgZmx1c2hfdGltZXN0YW1wLDxicj4NCsKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICZhbXA7b3V0W251bV0sIGxlZnRfbmJf b3V0KTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBsZWZ0X25iX291dCA9IG1heF9uYl9v dXQgLSBudW07PGJyPg0KK8KgIMKgIMKgIMKgfTxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBpZiAo KGdyb190eXBlcyAmYW1wOyBSVEVfR1JPX1RDUF9JUFY2KSAmYW1wOyZhbXA7IGxlZnRfbmJfb3V0 ICZndDsgMCkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoG51bSArPSBncm9fdGNwNl90 YmxfdGltZW91dF9mbHVzaCg8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqBncm9fY3R4LSZndDt0YmxzW1JURV9HUk9fVENQX0lQVjZfSU5ERVhdLDxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGZsdXNo X3RpbWVzdGFtcCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAmYW1wO291dFtudW1dLCBsZWZ0X25iX291dCk7PGJyPg0KKzxicj4NCsKgIMKgIMKg IMKgIH08YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCByZXR1cm4gbnVtOzxicj4NCmRpZmYgLS1naXQg YS9saWIvZ3JvL3J0ZV9ncm8uaCBiL2xpYi9ncm8vcnRlX2dyby5oPGJyPg0KaW5kZXggOWY5ZWQ0 OTM1YS4uYzgzZGZkOWFkMSAxMDA2NDQ8YnI+DQotLS0gYS9saWIvZ3JvL3J0ZV9ncm8uaDxicj4N CisrKyBiL2xpYi9ncm8vcnRlX2dyby5oPGJyPg0KQEAgLTM4LDYgKzM4LDkgQEAgZXh0ZXJuICZx dW90O0MmcXVvdDsgezxicj4NCsKgI2RlZmluZSBSVEVfR1JPX0lQVjRfVlhMQU5fVURQX0lQVjRf SU5ERVggMzxicj4NCsKgI2RlZmluZSBSVEVfR1JPX0lQVjRfVlhMQU5fVURQX0lQVjQgKDFVTEwg Jmx0OyZsdDsgUlRFX0dST19JUFY0X1ZYTEFOX1VEUF9JUFY0X0lOREVYKTxicj4NCsKgLyoqJmx0 OyBWeExBTiBVRFAvSVB2NCBHUk8gZmxhZy4gKi88YnI+DQorI2RlZmluZSBSVEVfR1JPX1RDUF9J UFY2X0lOREVYIDQ8YnI+DQorI2RlZmluZSBSVEVfR1JPX1RDUF9JUFY2ICgxVUxMICZsdDsmbHQ7 IFJURV9HUk9fVENQX0lQVjZfSU5ERVgpPGJyPg0KKy8qKiZsdDsgVENQL0lQdjYgR1JPIGZsYWcu ICovPGJyPg0KPGJyPg0KwqAvKio8YnI+DQrCoCAqIFN0cnVjdHVyZSB1c2VkIHRvIGNyZWF0ZSBH Uk8gY29udGV4dCBvYmplY3RzIG9yIHVzZWQgdG8gcGFzczxicj4NCi0tIDxicj4NCjIuMjUuMTxi cj48YmxvY2txdW90ZSBjbGFzcz0iZ21haWxfcXVvdGUiIHN0eWxlPSJtYXJnaW46MHB4IDBweCAw cHggMC44ZXg7Ym9yZGVyLWxlZnQ6MXB4IHNvbGlkIHJnYigyMDQsMjA0LDIwNCk7cGFkZGluZy1s ZWZ0OjFleCI+wqBIaSBKaXlhdSwgSW4gdGhlIHJlY2VudCBwYXRjaCBJIGhhdmUgbW92ZWQgdGhl IGZ1bmN0aW9ucyB0aGF0IGhhZCB0aGUgZXJyb3IgaW4gV2luZG93cyB0byB0aGUgaGVhZGVyIGZp bGUgYW5kIHNpbmNlIHRoYXQgaXMgdXNlZCBieSBncm9fdGNwNi5jIGFuZCBncm9fdGNwNC5jLCBJ IGhhdmUgbW92ZWQgaXQgdG8gZ3JvX3RjcF9pbnRlcm5hbC5oLiBUaGVyZSBhcmUgb3RoZXIgZnVu Y3Rpb25zIGFuZCBkcyByZXVzZWQgYnkgZ3JvX3Z4bGFuX3RjcDQuYywgSSBoYXZlIG1vdmVkIHRo ZW0gdG8gZ3JvX3RjcC5oIHNvIHRoYXQgdGhlIGZ1bmN0aW9ucyB0aGF0IGFyZSBub3QgdXNlZCBi eSBncm9fdnhsYW5fdGNwNC5jIHdpbGwgbm90IGJlIGluY2x1ZGVkLiA8YnI+PC9ibG9ja3F1b3Rl PjwvYmxvY2txdW90ZT48L2Rpdj48L2Rpdj4NCg== --00000000000097279c05fe2535f0--