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 67F7F42866; Wed, 29 Mar 2023 18:39:31 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id F186F40F18; Wed, 29 Mar 2023 18:39:30 +0200 (CEST) Received: from mail-yb1-f182.google.com (mail-yb1-f182.google.com [209.85.219.182]) by mails.dpdk.org (Postfix) with ESMTP id 51A0440EDF for ; Wed, 29 Mar 2023 18:39:29 +0200 (CEST) Received: by mail-yb1-f182.google.com with SMTP id p15so20079230ybl.9 for ; Wed, 29 Mar 2023 09:39:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680107968; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=oQs+E5l4jzAAdr++V/kF66lAKsjcq1BJnFVXzl9by6o=; b=SS2IzOApvJdEct7mgZmJOhLhv6cel1DSkmWyRe+hW2vfxRlOdzVQHBv29rbQK9UpKI s2znTSMhUdRABHEvcV48S/HEKimoqolkzN5mFLJB9X20Novaw8/tjhnU0J5eoOHWcBCZ yKq2h4OyDp0MSEMO3GNIDuI614SMEVliy8/RxajH+/Zf8JzBVnCSaKJIcK/t74N0qGBH +E2s5IzsQoQGtmSy5sQb8QFBeCakmqosmw/8XHpGDaxwK7Xkr8vvgCyyA9VVcbm/m7gm XN6+JYKIBoAXRZbSfUKgDz/vSHDoI9Y+f20nX3BS2pQit948ofIUi4E5JLIL4w/ElcLK iS6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680107968; 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=oQs+E5l4jzAAdr++V/kF66lAKsjcq1BJnFVXzl9by6o=; b=HAN8tUuuP0jHIFJMxASuE0FIBWKIZr5NVCEDFUVgB63AVotgHL0hYj+XXVsU6K/Rh+ t2gRQ5I2K7DwyWtxC9/8YcHLZrtQS0+ICxC2SQ5B/7FRcWWLA2L+m04Vqhj69iU0xiUH muIt/8H/3hnNuoe/KziVPeyVmS6YH8YD39HDFn/6iUSUB9qGrNBd8oCGFGiyueaV6xkb NJ02/LO4/nKRqUtyFCxmj6kkaglnW3isiQBOoSLZWeia+gF2TjBZFBH6NvpfZycXLmPM s0APw9XV8VrX439jbON35ijaprz6wLYJUka5iK3EpOXzro/irlr45Rm/yfOqtH54VXjf 19bA== X-Gm-Message-State: AAQBX9eXq0WCNU+ahrAHfPVsR7O8X78E+kDLM3CfIHLtp4JwMUZqyOir Qns/SUm6nReH0rqWAxRNtcSDRTR97t2TyWAZ7nSzAC2z X-Google-Smtp-Source: AKy350bJtmyhmefchbTBtS5oAVvSxTaTZCRNaJazrLq0Z7XwgD9HXhiWvFtaQMvmdmdzHBQQEX4tJP2NO+Et6zpUG08= X-Received: by 2002:a05:6902:1545:b0:b75:8ac3:d5dc with SMTP id r5-20020a056902154500b00b758ac3d5dcmr12904658ybu.2.1680107968270; Wed, 29 Mar 2023 09:39:28 -0700 (PDT) MIME-Version: 1.0 References: <20221020121309.14737-1-kparameshwar@kparameshwa-a02.vmware.com> In-Reply-To: <20221020121309.14737-1-kparameshwar@kparameshwa-a02.vmware.com> From: kumaraparameshwaran rathinavel Date: Wed, 29 Mar 2023 22:09:16 +0530 Message-ID: Subject: Re: [PATCH] gro : ipv6 changes to support GRO for TCP/ipv6 To: dev@dpdk.org Cc: jiayu.hu@intel.com, Thomas Monjalon Content-Type: multipart/alternative; boundary="000000000000a218b805f80c9e63" 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 --000000000000a218b805f80c9e63 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, I would like to get a review on the following patch where support is added for IPv6 GRO. Thanks, Param. On Thu, Oct 20, 2022 at 5:43=E2=80=AFPM Kumara Parameshwaran < kumaraparamesh92@gmail.com> wrote: > From: Kumara Parameshwaran > > 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. > > lib/gro/gro_tcp.h | 155 ++++++++++++++++ > lib/gro/gro_tcp4.c | 7 +- > lib/gro/gro_tcp4.h | 152 +-------------- > lib/gro/gro_tcp6.c | 388 +++++++++++++++++++++++++++++++++++++++ > lib/gro/gro_tcp6.h | 150 +++++++++++++++ > lib/gro/gro_vxlan_tcp4.c | 3 +- > lib/gro/gro_vxlan_tcp4.h | 3 +- > lib/gro/meson.build | 1 + > lib/gro/rte_gro.c | 86 +++++++-- > lib/gro/rte_gro.h | 3 + > 10 files changed, 777 insertions(+), 171 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 > > diff --git a/lib/gro/gro_tcp.h b/lib/gro/gro_tcp.h > new file mode 100644 > index 0000000000..16bce9d098 > --- /dev/null > +++ b/lib/gro/gro_tcp.h > @@ -0,0 +1,155 @@ > +#ifndef _GRO_TCP_H_ > +#define _GRO_TCP_H_ > + > +#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 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; > + /* 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; > +}; > + > +/* > + * 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->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_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->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_tcp4.c b/lib/gro/gro_tcp4.c > index 8f5e800250..eea2a72ecd 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.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, > @@ -177,7 +178,7 @@ insert_new_flow(struct gro_tcp4_tbl *tbl, > * update the packet length for the flushed packet. > */ > static inline void > -update_header(struct gro_tcp4_item *item) > +update_header(struct gro_tcp_item *item) > { > struct rte_ipv4_hdr *ipv4_hdr; > struct rte_mbuf *pkt =3D item->firstseg; > @@ -302,7 +303,7 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > sent_seq, ip_id, pkt->l4_len, tcp_dl, 0, > is_atomic); > if (cmp) { > - if (merge_two_tcp4_packets(&(tbl->items[cur_idx])= , > + if (merge_two_tcp_packets(&(tbl->items[cur_idx]), > pkt, cmp, sent_seq, ip_id= , > 0)) > return 1; > /* > diff --git a/lib/gro/gro_tcp4.h b/lib/gro/gro_tcp4.h > index 212f97a042..634a215b98 100644 > --- a/lib/gro/gro_tcp4.h > +++ b/lib/gro/gro_tcp4.h > @@ -5,22 +5,9 @@ > #ifndef _GRO_TCP4_H_ > #define _GRO_TCP4_H_ > > -#include > - > #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 */ > struct tcp4_flow_key { > struct rte_ether_addr eth_saddr; > @@ -42,42 +29,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 */ > @@ -195,111 +152,4 @@ is_same_tcp4_flow(struct tcp4_flow_key k1, struct > tcp4_flow_key k2) > (k1.dst_port =3D=3D k2.dst_port)); > } > > -/* > - * 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..7a739f2472 > --- /dev/null > +++ b/lib/gro/gro_tcp6.c > @@ -0,0 +1,388 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2017 Intel Corporation > + */ > + > +#include > +#include > +#include > + > +#include "gro_tcp6.h" > +#include "gro_tcp.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_item(struct gro_tcp6_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_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_item(struct gro_tcp6_tbl *tbl, > + struct rte_mbuf *pkt, > + uint64_t start_time, > + uint32_t prev_idx, > + uint32_t sent_seq, > + 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].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_tcp6_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_tcp6_tbl *tbl, > + struct tcp6_flow_key *src, > + rte_be32_t vtc_flow, > + 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); > + > + rte_ether_addr_copy(&(src->eth_saddr), &(dst->eth_saddr)); > + rte_ether_addr_copy(&(src->eth_daddr), &(dst->eth_daddr)); > + 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->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++; > + tbl->flows->vtc_flow =3D vtc_flow; > + > + 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; > + struct rte_tcp_hdr *tcp_hdr; > + uint32_t sent_seq; > + int32_t tcp_dl; > + uint16_t ip_tlen; > + struct tcp6_flow_key key; > + uint32_t cur_idx, prev_idx, item_idx; > + uint32_t i, max_flow_num, remaining_flow_num; > + int cmp; > + uint8_t find; > + rte_be32_t vtc_flow_diff; > + > + /* > + * 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 (struct rte_tcp_hdr *)((char *)ipv6_hdr + 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); > + /* > + * Trim the tail padding bytes. The IPv6 header is fixed to > + * 40 bytes unlike IPv4 that is variable. The length in the IPv6 > header > + * contains only length of TCP Header + TCP Payload, whereas IPv4 > header contains > + * length of IP Header + TCP Header + TCP Payload > + */ > + if (pkt->pkt_len > (uint32_t)(ip_tlen + pkt->l2_len + pkt->l3_len= )) > + rte_pktmbuf_trim(pkt, pkt->pkt_len - ip_tlen - pkt->l2_le= n > - pkt->l3_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; > + > + 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)); > + 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.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; > + 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)) { > + /* > + * IP version (4) Traffic Class (8) Flow > Label (20) > + * All fields except Traffic class should > be same > + */ > + vtc_flow_diff =3D (ipv6_hdr->vtc_flow ^ > tbl->flows->vtc_flow); > + if (vtc_flow_diff & htonl(0xF00FFFFF)) { > + continue; > + } > + find =3D 1; > + break; > + } > + remaining_flow_num--; > + } > + } > + > + /* > + * 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, true); > + if (item_idx =3D=3D INVALID_ARRAY_INDEX) > + return -1; > + if (insert_new_flow(tbl, &key, ipv6_hdr->vtc_flow, > item_idx) =3D=3D > + INVALID_ARRAY_INDEX) { > + /* > + * Fail to insert a new flow, so delete the > + * stored packet. > + */ > + delete_item(tbl, item_idx, 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, 0, pkt->l4_len, tcp_dl, 0, > + true); > + if (cmp) { > + if (merge_two_tcp_packets(&(tbl->items[cur_idx]), > + pkt, cmp, sent_seq, 0, 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, true) =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); > + > + /* Fail to find a neighbor, so store the packet into the flow. */ > + if (insert_new_item(tbl, pkt, start_time, prev_idx, sent_seq, > + true) =3D=3D INVALID_ARRAY_INDEX) > + return -1; > + > + return 0; > +} > + > +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_item(tbl, j, > 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..aea231adbb > --- /dev/null > +++ b/lib/gro/gro_tcp6.h > @@ -0,0 +1,150 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2017 Intel Corporation > + */ > + > +#ifndef _GRO_TCP6_H_ > +#define _GRO_TCP6_H_ > + > +#define INVALID_ARRAY_INDEX 0xffffffffUL > +#define GRO_TCP6_TBL_MAX_ITEM_NUM (1024UL * 1024UL) > + > +/* Header fields representing a TCP/IPv6 flow */ > +struct tcp6_flow_key { > + struct rte_ether_addr eth_saddr; > + struct rte_ether_addr eth_daddr; > + uint8_t src_addr[16]; > + uint8_t dst_addr[16]; > + > + uint32_t recv_ack; > + uint16_t src_port; > + uint16_t dst_port; > +}; > + > +struct gro_tcp6_flow { > + struct tcp6_flow_key key; > + rte_be32_t vtc_flow; > + /* > + * 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/IPv4 reassembly table, > + * and without updating checksums. > + * > + * @param tbl > + * TCP/IPv4 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/IPv4 > + * reassembly table. > + * > + * @param tbl > + * TCP/IPv4 reassembly table pointer > + * > + * @return > + * The number of packets in the table > + */ > +uint32_t gro_tcp6_tbl_pkt_count(void *tbl); > + > +/* > + * Check if two TCP/IPv4 packets belong to the same flow. > + */ > +static inline int > +is_same_tcp6_flow(struct tcp6_flow_key k1, struct tcp6_flow_key k2) > +{ > + return (!memcmp(&k1, &k2, sizeof(struct tcp6_flow_key))); > +} > + > +#endif > \ No newline at end of file > diff --git a/lib/gro/gro_vxlan_tcp4.c b/lib/gro/gro_vxlan_tcp4.c > index 3be4deb7c7..56b30b8c98 100644 > --- a/lib/gro/gro_vxlan_tcp4.c > +++ b/lib/gro/gro_vxlan_tcp4.c > @@ -7,6 +7,7 @@ > #include > #include > > +#include "gro_tcp.h" > #include "gro_vxlan_tcp4.h" > > void * > @@ -248,7 +249,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. */ > diff --git a/lib/gro/gro_vxlan_tcp4.h b/lib/gro/gro_vxlan_tcp4.h > index 7832942a68..d68d5fcd5b 100644 > --- a/lib/gro/gro_vxlan_tcp4.h > +++ b/lib/gro/gro_vxlan_tcp4.h > @@ -5,6 +5,7 @@ > #ifndef _GRO_VXLAN_TCP4_H_ > #define _GRO_VXLAN_TCP4_H_ > > +#include "gro_tcp.h" > #include "gro_tcp4.h" > > #define GRO_VXLAN_TCP4_TBL_MAX_ITEM_NUM (1024UL * 1024UL) > @@ -36,7 +37,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..c8180d24e3 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,7 +412,13 @@ 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 > + } 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]; > } > if (unprocess_num > 0) { > @@ -426,6 +473,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..ac5a464cf1 100644 > --- a/lib/gro/rte_gro.h > +++ b/lib/gro/rte_gro.h > @@ -37,6 +37,9 @@ extern "C" { > /**< UDP/IPv4 GRO flag */ > #define RTE_GRO_IPV4_VXLAN_UDP_IPV4_INDEX 3 > #define RTE_GRO_IPV4_VXLAN_UDP_IPV4 (1ULL << > RTE_GRO_IPV4_VXLAN_UDP_IPV4_INDEX) > + > +#define RTE_GRO_TCP_IPV6_INDEX 4 > +#define RTE_GRO_TCP_IPV6 (1ULL << RTE_GRO_TCP_IPV6_INDEX) > /**< VxLAN UDP/IPv4 GRO flag. */ > > /** > -- > 2.25.1 > > --000000000000a218b805f80c9e63 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 PGRpdiBkaXI9Imx0ciI+PGRpdj5IaSwgPGJyPjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+SSB3 b3VsZCBsaWtlIHRvIGdldCBhIHJldmlldyBvbiB0aGUgZm9sbG93aW5nIHBhdGNoIHdoZXJlIHN1 cHBvcnQgaXMgYWRkZWQgZm9yIElQdjYgR1JPLiA8YnI+PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRp dj5UaGFua3MsPC9kaXY+PGRpdj5QYXJhbS48YnI+PC9kaXY+PGRpdj48ZGl2IGRpcj0ibHRyIj48 YnI+PC9kaXY+PGJyPjxkaXYgY2xhc3M9ImdtYWlsX3F1b3RlIj48ZGl2IGRpcj0ibHRyIiBjbGFz cz0iZ21haWxfYXR0ciI+T24gVGh1LCBPY3QgMjAsIDIwMjIgYXQgNTo0M+KAr1BNIEt1bWFyYSBQ YXJhbWVzaHdhcmFuICZsdDs8YSBocmVmPSJtYWlsdG86a3VtYXJhcGFyYW1lc2g5MkBnbWFpbC5j b20iPmt1bWFyYXBhcmFtZXNoOTJAZ21haWwuY29tPC9hPiZndDsgd3JvdGU6PGJyPjwvZGl2Pjxi bG9ja3F1b3RlIGNsYXNzPSJnbWFpbF9xdW90ZSIgc3R5bGU9Im1hcmdpbjowcHggMHB4IDBweCAw LjhleDtib3JkZXItbGVmdDoxcHggc29saWQgcmdiKDIwNCwyMDQsMjA0KTtwYWRkaW5nLWxlZnQ6 MWV4Ij5Gcm9tOiBLdW1hcmEgUGFyYW1lc2h3YXJhbiAmbHQ7PGEgaHJlZj0ibWFpbHRvOmt1bWFy YXBhcmFtZXNoOTJAZ21haWwuY29tIiB0YXJnZXQ9Il9ibGFuayI+a3VtYXJhcGFyYW1lc2g5MkBn bWFpbC5jb208L2E+Jmd0Ozxicj4NCjxicj4NClRoZSBwYXRjaCBhZGRzIEdSTyBzdXBwb3J0IGZv ciBUQ1AvaXB2NiBwYWNrZXRzLiBUaGlzIGRvZXMgbm90PGJyPg0KaW5jbHVkZSB0aGUgc3VwcG9y dCBmb3IgdnhsYW4sIHVkcCBpcHY2IHBhY2tldHMuPGJyPg0KPGJyPg0KU2lnbmVkLW9mZi1ieTog S3VtYXJhIFBhcmFtZXNod2FyYW4gJmx0OzxhIGhyZWY9Im1haWx0bzprdW1hcmFwYXJhbWVzaDky QGdtYWlsLmNvbSIgdGFyZ2V0PSJfYmxhbmsiPmt1bWFyYXBhcmFtZXNoOTJAZ21haWwuY29tPC9h PiZndDs8YnI+DQotLS08YnI+DQp2MTo8YnI+DQrCoCDCoCDCoCDCoCAqIENoYW5nZXMgdG8gc3Vw cG9ydCBHUk8gZm9yIFRDUC9pcHY2IHBhY2tldHMuIFRoaXMgZG9lcyBub3QgaW5jbHVkZTxicj4N CsKgIMKgIMKgIMKgIMKgIHZ4bGFuIGNoYW5nZXMuIDxicj4NCsKgIMKgIMKgIMKgICogVGhlIEdS TyBpcyBwZXJmb3JtZWQgb25seSBmb3IgaXB2NiBwYWNrZXRzIHRoYXQgZG9lcyBub3QgY29udGFp biA8YnI+DQrCoCDCoCDCoCDCoCDCoGV4dGVuc2lvbiBoZWFkZXJzLiA8YnI+DQrCoCDCoCDCoCDC oCAqIFRoZSBsb2dpYyBmb3IgdGhlIFRDUCBjb2FsZXNjaW5nIHJlbWFpbnMgdGhlIHNhbWUsIGlu IGlwdjYgaGVhZGVyIDxicj4NCsKgIMKgIMKgIMKgIMKgIHRoZSBzb3VyY2UgYWRkcmVzcywgZGVz dGluYXRpb24gYWRkcmVzcywgZmxvdyBsYWJlbCwgdmVyc2lvbiBmaWVsZHMgPGJyPg0KwqAgwqAg wqAgwqAgwqAgYXJlIGV4cGVjdGVkIHRvIGJlIHRoZSBzYW1lLiA8YnI+DQrCoCDCoCDCoCDCoCAq IFJlLW9yZ2FuaXNlZCB0aGUgY29kZSB0byByZXVzZSBjZXJ0YWluIHRjcCBmdW5jdGlvbnMgZm9y IGJvdGggaXB2NCBhbmQgPGJyPg0KwqAgwqAgwqAgwqAgwqAgaXB2NiBmbG93cy48YnI+DQo8YnI+ DQrCoGxpYi9ncm8vZ3JvX3RjcC5owqAgwqAgwqAgwqAgfCAxNTUgKysrKysrKysrKysrKysrKzxi cj4NCsKgbGliL2dyby9ncm9fdGNwNC5jwqAgwqAgwqAgwqB8wqAgwqA3ICstPGJyPg0KwqBsaWIv Z3JvL2dyb190Y3A0LmjCoCDCoCDCoCDCoHwgMTUyICstLS0tLS0tLS0tLS0tLTxicj4NCsKgbGli L2dyby9ncm9fdGNwNi5jwqAgwqAgwqAgwqB8IDM4OCArKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKys8YnI+DQrCoGxpYi9ncm8vZ3JvX3RjcDYuaMKgIMKgIMKgIMKgfCAxNTAg KysrKysrKysrKysrKysrPGJyPg0KwqBsaWIvZ3JvL2dyb192eGxhbl90Y3A0LmMgfMKgIMKgMyAr LTxicj4NCsKgbGliL2dyby9ncm9fdnhsYW5fdGNwNC5oIHzCoCDCoDMgKy08YnI+DQrCoGxpYi9n cm8vbWVzb24uYnVpbGTCoCDCoCDCoCB8wqAgwqAxICs8YnI+DQrCoGxpYi9ncm8vcnRlX2dyby5j wqAgwqAgwqAgwqAgfMKgIDg2ICsrKysrKystLTxicj4NCsKgbGliL2dyby9ydGVfZ3JvLmjCoCDC oCDCoCDCoCB8wqAgwqAzICs8YnI+DQrCoDEwIGZpbGVzIGNoYW5nZWQsIDc3NyBpbnNlcnRpb25z KCspLCAxNzEgZGVsZXRpb25zKC0pPGJyPg0KwqBjcmVhdGUgbW9kZSAxMDA2NDQgbGliL2dyby9n cm9fdGNwLmg8YnI+DQrCoGNyZWF0ZSBtb2RlIDEwMDY0NCBsaWIvZ3JvL2dyb190Y3A2LmM8YnI+ DQrCoGNyZWF0ZSBtb2RlIDEwMDY0NCBsaWIvZ3JvL2dyb190Y3A2Lmg8YnI+DQo8YnI+DQpkaWZm IC0tZ2l0IGEvbGliL2dyby9ncm9fdGNwLmggYi9saWIvZ3JvL2dyb190Y3AuaDxicj4NCm5ldyBm aWxlIG1vZGUgMTAwNjQ0PGJyPg0KaW5kZXggMDAwMDAwMDAwMC4uMTZiY2U5ZDA5ODxicj4NCi0t LSAvZGV2L251bGw8YnI+DQorKysgYi9saWIvZ3JvL2dyb190Y3AuaDxicj4NCkBAIC0wLDAgKzEs MTU1IEBAPGJyPg0KKyNpZm5kZWYgX0dST19UQ1BfSF88YnI+DQorI2RlZmluZSBfR1JPX1RDUF9I Xzxicj4NCis8YnI+DQorI2luY2x1ZGUgJmx0O3J0ZV90Y3AuaCZndDs8YnI+DQorPGJyPg0KKy8q PGJyPg0KKyAqIFRoZSBtYXggbGVuZ3RoIG9mIGEgSVB2NCBwYWNrZXQsIHdoaWNoIGluY2x1ZGVz IHRoZSBsZW5ndGggb2YgdGhlIEwzPGJyPg0KKyAqIGhlYWRlciwgdGhlIEw0IGhlYWRlciBhbmQg dGhlIGRhdGEgcGF5bG9hZC48YnI+DQorICovPGJyPg0KKyNkZWZpbmUgTUFYX0lQX1BLVF9MRU5H VEggVUlOVDE2X01BWDxicj4NCis8YnI+DQorLyogVGhlIG1heGltdW0gVENQIGhlYWRlciBsZW5n dGggKi88YnI+DQorI2RlZmluZSBNQVhfVENQX0hMRU4gNjA8YnI+DQorI2RlZmluZSBJTlZBTElE X1RDUF9IRFJMRU4obGVuKSBcPGJyPg0KK8KgIMKgIMKgIMKgKCgobGVuKSAmbHQ7IHNpemVvZihz dHJ1Y3QgcnRlX3RjcF9oZHIpKSB8fCAoKGxlbikgJmd0OyBNQVhfVENQX0hMRU4pKTxicj4NCis8 YnI+DQorc3RydWN0IGdyb190Y3BfaXRlbSB7PGJyPg0KK8KgIMKgIMKgIMKgLyo8YnI+DQorwqAg wqAgwqAgwqAgKiBUaGUgZmlyc3QgTUJVRiBzZWdtZW50IG9mIHRoZSBwYWNrZXQuIElmIHRoZSB2 YWx1ZTxicj4NCivCoCDCoCDCoCDCoCAqIGlzIE5VTEwsIGl0IG1lYW5zIHRoZSBpdGVtIGlzIGVt cHR5Ljxicj4NCivCoCDCoCDCoCDCoCAqLzxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBydGVfbWJ1 ZiAqZmlyc3RzZWc7PGJyPg0KK8KgIMKgIMKgIMKgLyogVGhlIGxhc3QgTUJVRiBzZWdtZW50IG9m IHRoZSBwYWNrZXQgKi88YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX21idWYgKmxhc3RzZWc7 PGJyPg0KK8KgIMKgIMKgIMKgLyo8YnI+DQorwqAgwqAgwqAgwqAgKiBUaGUgdGltZSB3aGVuIHRo ZSBmaXJzdCBwYWNrZXQgaXMgaW5zZXJ0ZWQgaW50byB0aGUgdGFibGUuPGJyPg0KK8KgIMKgIMKg IMKgICogVGhpcyB2YWx1ZSB3b24mIzM5O3QgYmUgdXBkYXRlZCwgZXZlbiBpZiB0aGUgcGFja2V0 IGlzIG1lcmdlZDxicj4NCivCoCDCoCDCoCDCoCAqIHdpdGggb3RoZXIgcGFja2V0cy48YnI+DQor wqAgwqAgwqAgwqAgKi88YnI+DQorwqAgwqAgwqAgwqB1aW50NjRfdCBzdGFydF90aW1lOzxicj4N CivCoCDCoCDCoCDCoC8qPGJyPg0KK8KgIMKgIMKgIMKgICogbmV4dF9wa3RfaWR4IGlzIHVzZWQg dG8gY2hhaW4gdGhlIHBhY2tldHMgdGhhdDxicj4NCivCoCDCoCDCoCDCoCAqIGFyZSBpbiB0aGUg c2FtZSBmbG93IGJ1dCBjYW4mIzM5O3QgYmUgbWVyZ2VkIHRvZ2V0aGVyPGJyPg0KK8KgIMKgIMKg IMKgICogKGUuZy4gY2F1c2VkIGJ5IHBhY2tldCByZW9yZGVyaW5nKS48YnI+DQorwqAgwqAgwqAg wqAgKi88YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBuZXh0X3BrdF9pZHg7PGJyPg0KK8KgIMKg IMKgIMKgLyogVENQIHNlcXVlbmNlIG51bWJlciBvZiB0aGUgcGFja2V0ICovPGJyPg0KK8KgIMKg IMKgIMKgdWludDMyX3Qgc2VudF9zZXE7PGJyPg0KK8KgIMKgIMKgIMKgLyogSVB2NCBJRCBvZiB0 aGUgcGFja2V0ICovPGJyPg0KK8KgIMKgIMKgIMKgdWludDE2X3QgaXBfaWQ7PGJyPg0KK8KgIMKg IMKgIMKgLyogdGhlIG51bWJlciBvZiBtZXJnZWQgcGFja2V0cyAqLzxicj4NCivCoCDCoCDCoCDC oHVpbnQxNl90IG5iX21lcmdlZDs8YnI+DQorwqAgwqAgwqAgwqAvKiBJbmRpY2F0ZSBpZiBJUHY0 IElEIGNhbiBiZSBpZ25vcmVkICovPGJyPg0KK8KgIMKgIMKgIMKgdWludDhfdCBpc19hdG9taWM7 PGJyPg0KK307PGJyPg0KKzxicj4NCisvKjxicj4NCisgKiBNZXJnZSB0d28gVENQIHBhY2tldHMg d2l0aG91dCB1cGRhdGluZyBjaGVja3N1bXMuPGJyPg0KKyAqIElmIGNtcCBpcyBsYXJnZXIgdGhh biAwLCBhcHBlbmQgdGhlIG5ldyBwYWNrZXQgdG8gdGhlPGJyPg0KKyAqIG9yaWdpbmFsIHBhY2tl dC4gT3RoZXJ3aXNlLCBwcmUtcGVuZCB0aGUgbmV3IHBhY2tldCB0bzxicj4NCisgKiB0aGUgb3Jp Z2luYWwgcGFja2V0Ljxicj4NCisgKi88YnI+DQorc3RhdGljIGlubGluZSBpbnQ8YnI+DQorbWVy Z2VfdHdvX3RjcF9wYWNrZXRzKHN0cnVjdCBncm9fdGNwX2l0ZW0gKml0ZW0sPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgc3RydWN0IHJ0ZV9tYnVmICpwa3QsPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgaW50IGNtcCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MzJf dCBzZW50X3NlcSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCBpcF9pZCw8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCBsMl9vZmZzZXQpPGJyPg0KK3s8 YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX21idWYgKnBrdF9oZWFkLCAqcGt0X3RhaWwsICps YXN0c2VnOzxicj4NCivCoCDCoCDCoCDCoHVpbnQxNl90IGhkcl9sZW4sIGwyX2xlbjs8YnI+DQor PGJyPg0KK8KgIMKgIMKgIMKgaWYgKGNtcCAmZ3Q7IDApIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBwa3RfaGVhZCA9IGl0ZW0tJmd0O2ZpcnN0c2VnOzxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoHBrdF90YWlsID0gcGt0Ozxicj4NCivCoCDCoCDCoCDCoH0gZWxzZSB7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcGt0X2hlYWQgPSBwa3Q7PGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgcGt0X3RhaWwgPSBpdGVtLSZndDtmaXJzdHNlZzs8YnI+DQorwqAgwqAgwqAg wqB9PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoC8qIGNoZWNrIGlmIHRoZSBJUHY0IHBhY2tldCBs ZW5ndGggaXMgZ3JlYXRlciB0aGFuIHRoZSBtYXggdmFsdWUgKi88YnI+DQorwqAgwqAgwqAgwqBo ZHJfbGVuID0gbDJfb2Zmc2V0ICsgcGt0X2hlYWQtJmd0O2wyX2xlbiArIHBrdF9oZWFkLSZndDts M19sZW4gKzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdF9oZWFkLSZndDtsNF9sZW47 PGJyPg0KK8KgIMKgIMKgIMKgbDJfbGVuID0gbDJfb2Zmc2V0ICZndDsgMCA/IHBrdF9oZWFkLSZn dDtvdXRlcl9sMl9sZW4gOiBwa3RfaGVhZC0mZ3Q7bDJfbGVuOzxicj4NCivCoCDCoCDCoCDCoGlm ICh1bmxpa2VseShwa3RfaGVhZC0mZ3Q7cGt0X2xlbiAtIGwyX2xlbiArIHBrdF90YWlsLSZndDtw a3RfbGVuIC08YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBoZHJfbGVuICZndDsgTUFYX0lQX1BLVF9MRU5HVEgpKTxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoHJldHVybiAwOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAvKiByZW1vdmUgdGhl IHBhY2tldCBoZWFkZXIgZm9yIHRoZSB0YWlsIHBhY2tldCAqLzxicj4NCivCoCDCoCDCoCDCoHJ0 ZV9wa3RtYnVmX2Fkaihwa3RfdGFpbCwgaGRyX2xlbik7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDC oC8qIGNoYWluIHR3byBwYWNrZXRzIHRvZ2V0aGVyICovPGJyPg0KK8KgIMKgIMKgIMKgaWYgKGNt cCAmZ3Q7IDApIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpdGVtLSZndDtsYXN0c2Vn LSZndDtuZXh0ID0gcGt0Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW0tJmd0O2xh c3RzZWcgPSBydGVfcGt0bWJ1Zl9sYXN0c2VnKHBrdCk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgLyogdXBkYXRlIElQIElEIHRvIHRoZSBsYXJnZXIgdmFsdWUgKi88YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBpdGVtLSZndDtpcF9pZCA9IGlwX2lkOzxicj4NCivCoCDCoCDCoCDC oH0gZWxzZSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbGFzdHNlZyA9IHJ0ZV9wa3Rt YnVmX2xhc3RzZWcocGt0KTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBsYXN0c2VnLSZn dDtuZXh0ID0gaXRlbS0mZ3Q7Zmlyc3RzZWc7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg aXRlbS0mZ3Q7Zmlyc3RzZWcgPSBwa3Q7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyog dXBkYXRlIHNlbnRfc2VxIHRvIHRoZSBzbWFsbGVyIHZhbHVlICovPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgaXRlbS0mZ3Q7c2VudF9zZXEgPSBzZW50X3NlcTs8YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqBpdGVtLSZndDtpcF9pZCA9IGlwX2lkOzxicj4NCivCoCDCoCDCoCDCoH08 YnI+DQorwqAgwqAgwqAgwqBpdGVtLSZndDtuYl9tZXJnZWQrKzs8YnI+DQorPGJyPg0KK8KgIMKg IMKgIMKgLyogdXBkYXRlIE1CVUYgbWV0YWRhdGEgZm9yIHRoZSBtZXJnZWQgcGFja2V0ICovPGJy Pg0KK8KgIMKgIMKgIMKgcGt0X2hlYWQtJmd0O25iX3NlZ3MgKz0gcGt0X3RhaWwtJmd0O25iX3Nl Z3M7PGJyPg0KK8KgIMKgIMKgIMKgcGt0X2hlYWQtJmd0O3BrdF9sZW4gKz0gcGt0X3RhaWwtJmd0 O3BrdF9sZW47PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoHJldHVybiAxOzxicj4NCit9PGJyPg0K Kzxicj4NCisvKjxicj4NCisgKiBDaGVjayBpZiB0d28gVENQL0lQdjQgcGFja2V0cyBhcmUgbmVp Z2hib3JzLjxicj4NCisgKi88YnI+DQorc3RhdGljIGlubGluZSBpbnQ8YnI+DQorY2hlY2tfc2Vx X29wdGlvbihzdHJ1Y3QgZ3JvX3RjcF9pdGVtICppdGVtLDxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoHN0cnVjdCBydGVfdGNwX2hkciAqdGNwaCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqB1aW50MzJfdCBzZW50X3NlcSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50 MTZfdCBpcF9pZCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCB0Y3BfaGws PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDE2X3QgdGNwX2RsLDxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGwyX29mZnNldCw8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqB1aW50OF90IGlzX2F0b21pYyk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHN0 cnVjdCBydGVfbWJ1ZiAqcGt0X29yaWcgPSBpdGVtLSZndDtmaXJzdHNlZzs8YnI+DQorwqAgwqAg wqAgwqBjaGFyICppcGhfb3JpZzs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX3RjcF9oZHIg KnRjcGhfb3JpZzs8YnI+DQorwqAgwqAgwqAgwqB1aW50MTZfdCBsZW4sIHRjcF9obF9vcmlnOzxi cj4NCis8YnI+DQorwqAgwqAgwqAgwqBpcGhfb3JpZyA9IChjaGFyICopKHJ0ZV9wa3RtYnVmX210 b2QocGt0X29yaWcsIGNoYXIgKikgKyA8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgbDJf b2Zmc2V0ICsgcGt0X29yaWctJmd0O2wyX2xlbik7PGJyPg0KK8KgIMKgIMKgIMKgdGNwaF9vcmln ID0gKHN0cnVjdCBydGVfdGNwX2hkciAqKShpcGhfb3JpZyArIHBrdF9vcmlnLSZndDtsM19sZW4p Ozxicj4NCivCoCDCoCDCoCDCoHRjcF9obF9vcmlnID0gcGt0X29yaWctJmd0O2w0X2xlbjs8YnI+ DQorPGJyPg0KK8KgIMKgIMKgIMKgLyogQ2hlY2sgaWYgVENQIG9wdGlvbiBmaWVsZHMgZXF1YWwg Ki88YnI+DQorwqAgwqAgwqAgwqBsZW4gPSBSVEVfTUFYKHRjcF9obCwgdGNwX2hsX29yaWcpIC0g c2l6ZW9mKHN0cnVjdCBydGVfdGNwX2hkcik7PGJyPg0KK8KgIMKgIMKgIMKgaWYgKCh0Y3BfaGwg IT0gdGNwX2hsX29yaWcpIHx8ICgobGVuICZndDsgMCkgJmFtcDsmYW1wOzxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoChtZW1jbXAodGNwaCArIDEs IHRjcGhfb3JpZyArIDEsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbGVuKSAhPSAwKSkpPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgcmV0dXJuIDA7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoC8qIERvbiYjMzk7dCBt ZXJnZSBwYWNrZXRzIHdob3NlIERGIGJpdHMgYXJlIGRpZmZlcmVudCAqLzxicj4NCivCoCDCoCDC oCDCoGlmICh1bmxpa2VseShpdGVtLSZndDtpc19hdG9taWMgXiBpc19hdG9taWMpKTxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiAwOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAv KiBjaGVjayBpZiB0aGUgdHdvIHBhY2tldHMgYXJlIG5laWdoYm9ycyAqLzxicj4NCivCoCDCoCDC oCDCoGxlbiA9IHBrdF9vcmlnLSZndDtwa3RfbGVuIC0gbDJfb2Zmc2V0IC0gcGt0X29yaWctJmd0 O2wyX2xlbiAtPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcGt0X29yaWctJmd0O2wzX2xl biAtIHRjcF9obF9vcmlnOzxicj4NCivCoCDCoCDCoCDCoGlmICgoc2VudF9zZXEgPT0gaXRlbS0m Z3Q7c2VudF9zZXEgKyBsZW4pICZhbXA7JmFtcDsgKGlzX2F0b21pYyB8fDxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoChpcF9pZCA9PSBpdGVtLSZn dDtpcF9pZCArIDEpKSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiBhcHBlbmQgdGhl IG5ldyBwYWNrZXQgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gMTs8YnI+ DQorwqAgwqAgwqAgwqBlbHNlIGlmICgoc2VudF9zZXEgKyB0Y3BfZGwgPT0gaXRlbS0mZ3Q7c2Vu dF9zZXEpICZhbXA7JmFtcDsgKGlzX2F0b21pYyB8fDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoChpcF9pZCArIGl0ZW0tJmd0O25iX21lcmdlZCA9 PSBpdGVtLSZndDtpcF9pZCkpKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8qIHByZS1w ZW5kIHRoZSBuZXcgcGFja2V0ICovPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJu IC0xOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqByZXR1cm4gMDs8YnI+DQorfTxicj4NCis8YnI+ DQorI2VuZGlmPGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vZ3JvX3RjcDQuYyBiL2xpYi9ncm8v Z3JvX3RjcDQuYzxicj4NCmluZGV4IDhmNWU4MDAyNTAuLmVlYTJhNzJlY2QgMTAwNjQ0PGJyPg0K LS0tIGEvbGliL2dyby9ncm9fdGNwNC5jPGJyPg0KKysrIGIvbGliL2dyby9ncm9fdGNwNC5jPGJy Pg0KQEAgLTcsNiArNyw3IEBAPGJyPg0KwqAjaW5jbHVkZSAmbHQ7cnRlX2V0aGRldi5oJmd0Ozxi cj4NCjxicj4NCsKgI2luY2x1ZGUgJnF1b3Q7Z3JvX3RjcDQuaCZxdW90Ozxicj4NCisjaW5jbHVk ZSAmcXVvdDtncm9fdGNwLmgmcXVvdDs8YnI+DQo8YnI+DQrCoHZvaWQgKjxicj4NCsKgZ3JvX3Rj cDRfdGJsX2NyZWF0ZSh1aW50MTZfdCBzb2NrZXRfaWQsPGJyPg0KQEAgLTMwLDcgKzMxLDcgQEAg Z3JvX3RjcDRfdGJsX2NyZWF0ZSh1aW50MTZfdCBzb2NrZXRfaWQsPGJyPg0KwqAgwqAgwqAgwqAg aWYgKHRibCA9PSBOVUxMKTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHJldHVybiBOVUxM Ozxicj4NCjxicj4NCi3CoCDCoCDCoCDCoHNpemUgPSBzaXplb2Yoc3RydWN0IGdyb190Y3A0X2l0 ZW0pICogZW50cmllc19udW07PGJyPg0KK8KgIMKgIMKgIMKgc2l6ZSA9IHNpemVvZihzdHJ1Y3Qg Z3JvX3RjcF9pdGVtKSAqIGVudHJpZXNfbnVtOzxicj4NCsKgIMKgIMKgIMKgIHRibC0mZ3Q7aXRl bXMgPSBydGVfem1hbGxvY19zb2NrZXQoX19mdW5jX18sPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgc2l6ZSw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCBSVEVfQ0FDSEVfTElORV9TSVpFLDxicj4NCkBAIC0xNzcsNyArMTc4LDcgQEAgaW5z ZXJ0X25ld19mbG93KHN0cnVjdCBncm9fdGNwNF90YmwgKnRibCw8YnI+DQrCoCAqIHVwZGF0ZSB0 aGUgcGFja2V0IGxlbmd0aCBmb3IgdGhlIGZsdXNoZWQgcGFja2V0Ljxicj4NCsKgICovPGJyPg0K wqBzdGF0aWMgaW5saW5lIHZvaWQ8YnI+DQotdXBkYXRlX2hlYWRlcihzdHJ1Y3QgZ3JvX3RjcDRf aXRlbSAqaXRlbSk8YnI+DQordXBkYXRlX2hlYWRlcihzdHJ1Y3QgZ3JvX3RjcF9pdGVtICppdGVt KTxicj4NCsKgezxicj4NCsKgIMKgIMKgIMKgIHN0cnVjdCBydGVfaXB2NF9oZHIgKmlwdjRfaGRy Ozxicj4NCsKgIMKgIMKgIMKgIHN0cnVjdCBydGVfbWJ1ZiAqcGt0ID0gaXRlbS0mZ3Q7Zmlyc3Rz ZWc7PGJyPg0KQEAgLTMwMiw3ICszMDMsNyBAQCBncm9fdGNwNF9yZWFzc2VtYmxlKHN0cnVjdCBy dGVfbWJ1ZiAqcGt0LDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIHNlbnRfc2VxLCBpcF9pZCwgcGt0LSZndDtsNF9sZW4sIHRjcF9kbCwgMCw8YnI+ DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpc19hdG9t aWMpOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChjbXApIHs8YnI+DQotwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAobWVyZ2VfdHdvX3RjcDRfcGFja2V0cygm YW1wOyh0YmwtJmd0O2l0ZW1zW2N1cl9pZHhdKSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqBpZiAobWVyZ2VfdHdvX3RjcF9wYWNrZXRzKCZhbXA7KHRibC0mZ3Q7aXRl bXNbY3VyX2lkeF0pLDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHBrdCwgY21wLCBzZW50X3NlcSwgaXBf aWQsIDApKTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIHJldHVybiAxOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIC8q PGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vZ3JvX3RjcDQuaCBiL2xpYi9ncm8vZ3JvX3RjcDQu aDxicj4NCmluZGV4IDIxMmY5N2EwNDIuLjYzNGEyMTViOTggMTAwNjQ0PGJyPg0KLS0tIGEvbGli L2dyby9ncm9fdGNwNC5oPGJyPg0KKysrIGIvbGliL2dyby9ncm9fdGNwNC5oPGJyPg0KQEAgLTUs MjIgKzUsOSBAQDxicj4NCsKgI2lmbmRlZiBfR1JPX1RDUDRfSF88YnI+DQrCoCNkZWZpbmUgX0dS T19UQ1A0X0hfPGJyPg0KPGJyPg0KLSNpbmNsdWRlICZsdDtydGVfdGNwLmgmZ3Q7PGJyPg0KLTxi cj4NCsKgI2RlZmluZSBJTlZBTElEX0FSUkFZX0lOREVYIDB4ZmZmZmZmZmZVTDxicj4NCsKgI2Rl ZmluZSBHUk9fVENQNF9UQkxfTUFYX0lURU1fTlVNICgxMDI0VUwgKiAxMDI0VUwpPGJyPg0KPGJy Pg0KLS8qPGJyPg0KLSAqIFRoZSBtYXggbGVuZ3RoIG9mIGEgSVB2NCBwYWNrZXQsIHdoaWNoIGlu Y2x1ZGVzIHRoZSBsZW5ndGggb2YgdGhlIEwzPGJyPg0KLSAqIGhlYWRlciwgdGhlIEw0IGhlYWRl ciBhbmQgdGhlIGRhdGEgcGF5bG9hZC48YnI+DQotICovPGJyPg0KLSNkZWZpbmUgTUFYX0lQVjRf UEtUX0xFTkdUSCBVSU5UMTZfTUFYPGJyPg0KLTxicj4NCi0vKiBUaGUgbWF4aW11bSBUQ1AgaGVh ZGVyIGxlbmd0aCAqLzxicj4NCi0jZGVmaW5lIE1BWF9UQ1BfSExFTiA2MDxicj4NCi0jZGVmaW5l IElOVkFMSURfVENQX0hEUkxFTihsZW4pIFw8YnI+DQotwqAgwqAgwqAgwqAoKChsZW4pICZsdDsg c2l6ZW9mKHN0cnVjdCBydGVfdGNwX2hkcikpIHx8ICgobGVuKSAmZ3Q7IE1BWF9UQ1BfSExFTikp PGJyPg0KLTxicj4NCsKgLyogSGVhZGVyIGZpZWxkcyByZXByZXNlbnRpbmcgYSBUQ1AvSVB2NCBm bG93ICovPGJyPg0KwqBzdHJ1Y3QgdGNwNF9mbG93X2tleSB7PGJyPg0KwqAgwqAgwqAgwqAgc3Ry dWN0IHJ0ZV9ldGhlcl9hZGRyIGV0aF9zYWRkcjs8YnI+DQpAQCAtNDIsNDIgKzI5LDEyIEBAIHN0 cnVjdCBncm9fdGNwNF9mbG93IHs8YnI+DQrCoCDCoCDCoCDCoCB1aW50MzJfdCBzdGFydF9pbmRl eDs8YnI+DQrCoH07PGJyPg0KPGJyPg0KLXN0cnVjdCBncm9fdGNwNF9pdGVtIHs8YnI+DQotwqAg wqAgwqAgwqAvKjxicj4NCi3CoCDCoCDCoCDCoCAqIFRoZSBmaXJzdCBNQlVGIHNlZ21lbnQgb2Yg dGhlIHBhY2tldC4gSWYgdGhlIHZhbHVlPGJyPg0KLcKgIMKgIMKgIMKgICogaXMgTlVMTCwgaXQg bWVhbnMgdGhlIGl0ZW0gaXMgZW1wdHkuPGJyPg0KLcKgIMKgIMKgIMKgICovPGJyPg0KLcKgIMKg IMKgIMKgc3RydWN0IHJ0ZV9tYnVmICpmaXJzdHNlZzs8YnI+DQotwqAgwqAgwqAgwqAvKiBUaGUg bGFzdCBNQlVGIHNlZ21lbnQgb2YgdGhlIHBhY2tldCAqLzxicj4NCi3CoCDCoCDCoCDCoHN0cnVj dCBydGVfbWJ1ZiAqbGFzdHNlZzs8YnI+DQotwqAgwqAgwqAgwqAvKjxicj4NCi3CoCDCoCDCoCDC oCAqIFRoZSB0aW1lIHdoZW4gdGhlIGZpcnN0IHBhY2tldCBpcyBpbnNlcnRlZCBpbnRvIHRoZSB0 YWJsZS48YnI+DQotwqAgwqAgwqAgwqAgKiBUaGlzIHZhbHVlIHdvbiYjMzk7dCBiZSB1cGRhdGVk LCBldmVuIGlmIHRoZSBwYWNrZXQgaXMgbWVyZ2VkPGJyPg0KLcKgIMKgIMKgIMKgICogd2l0aCBv dGhlciBwYWNrZXRzLjxicj4NCi3CoCDCoCDCoCDCoCAqLzxicj4NCi3CoCDCoCDCoCDCoHVpbnQ2 NF90IHN0YXJ0X3RpbWU7PGJyPg0KLcKgIMKgIMKgIMKgLyo8YnI+DQotwqAgwqAgwqAgwqAgKiBu ZXh0X3BrdF9pZHggaXMgdXNlZCB0byBjaGFpbiB0aGUgcGFja2V0cyB0aGF0PGJyPg0KLcKgIMKg IMKgIMKgICogYXJlIGluIHRoZSBzYW1lIGZsb3cgYnV0IGNhbiYjMzk7dCBiZSBtZXJnZWQgdG9n ZXRoZXI8YnI+DQotwqAgwqAgwqAgwqAgKiAoZS5nLiBjYXVzZWQgYnkgcGFja2V0IHJlb3JkZXJp bmcpLjxicj4NCi3CoCDCoCDCoCDCoCAqLzxicj4NCi3CoCDCoCDCoCDCoHVpbnQzMl90IG5leHRf cGt0X2lkeDs8YnI+DQotwqAgwqAgwqAgwqAvKiBUQ1Agc2VxdWVuY2UgbnVtYmVyIG9mIHRoZSBw YWNrZXQgKi88YnI+DQotwqAgwqAgwqAgwqB1aW50MzJfdCBzZW50X3NlcTs8YnI+DQotwqAgwqAg wqAgwqAvKiBJUHY0IElEIG9mIHRoZSBwYWNrZXQgKi88YnI+DQotwqAgwqAgwqAgwqB1aW50MTZf dCBpcF9pZDs8YnI+DQotwqAgwqAgwqAgwqAvKiB0aGUgbnVtYmVyIG9mIG1lcmdlZCBwYWNrZXRz ICovPGJyPg0KLcKgIMKgIMKgIMKgdWludDE2X3QgbmJfbWVyZ2VkOzxicj4NCi3CoCDCoCDCoCDC oC8qIEluZGljYXRlIGlmIElQdjQgSUQgY2FuIGJlIGlnbm9yZWQgKi88YnI+DQotwqAgwqAgwqAg wqB1aW50OF90IGlzX2F0b21pYzs8YnI+DQotfTs8YnI+DQotPGJyPg0KwqAvKjxicj4NCsKgICog VENQL0lQdjQgcmVhc3NlbWJseSB0YWJsZSBzdHJ1Y3R1cmUuPGJyPg0KwqAgKi88YnI+DQrCoHN0 cnVjdCBncm9fdGNwNF90Ymwgezxicj4NCsKgIMKgIMKgIMKgIC8qIGl0ZW0gYXJyYXkgKi88YnI+ DQotwqAgwqAgwqAgwqBzdHJ1Y3QgZ3JvX3RjcDRfaXRlbSAqaXRlbXM7PGJyPg0KK8KgIMKgIMKg IMKgc3RydWN0IGdyb190Y3BfaXRlbSAqaXRlbXM7PGJyPg0KwqAgwqAgwqAgwqAgLyogZmxvdyBh cnJheSAqLzxicj4NCsKgIMKgIMKgIMKgIHN0cnVjdCBncm9fdGNwNF9mbG93ICpmbG93czs8YnI+ DQrCoCDCoCDCoCDCoCAvKiBjdXJyZW50IGl0ZW0gbnVtYmVyICovPGJyPg0KQEAgLTE5NSwxMTEg KzE1Miw0IEBAIGlzX3NhbWVfdGNwNF9mbG93KHN0cnVjdCB0Y3A0X2Zsb3dfa2V5IGsxLCBzdHJ1 Y3QgdGNwNF9mbG93X2tleSBrMik8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCAoazEuZHN0X3BvcnQgPT0gazIuZHN0X3BvcnQpKTs8YnI+DQrCoH08YnI+DQo8YnI+DQot Lyo8YnI+DQotICogTWVyZ2UgdHdvIFRDUC9JUHY0IHBhY2tldHMgd2l0aG91dCB1cGRhdGluZyBj aGVja3N1bXMuPGJyPg0KLSAqIElmIGNtcCBpcyBsYXJnZXIgdGhhbiAwLCBhcHBlbmQgdGhlIG5l dyBwYWNrZXQgdG8gdGhlPGJyPg0KLSAqIG9yaWdpbmFsIHBhY2tldC4gT3RoZXJ3aXNlLCBwcmUt cGVuZCB0aGUgbmV3IHBhY2tldCB0bzxicj4NCi0gKiB0aGUgb3JpZ2luYWwgcGFja2V0Ljxicj4N Ci0gKi88YnI+DQotc3RhdGljIGlubGluZSBpbnQ8YnI+DQotbWVyZ2VfdHdvX3RjcDRfcGFja2V0 cyhzdHJ1Y3QgZ3JvX3RjcDRfaXRlbSAqaXRlbSw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpbnQg Y21wLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRfc2VxLDxicj4N Ci3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGlwX2lkLDxicj4NCi3CoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHVpbnQxNl90IGwyX29mZnNldCk8YnI+DQotezxicj4NCi3CoCDCoCDCoCDC oHN0cnVjdCBydGVfbWJ1ZiAqcGt0X2hlYWQsICpwa3RfdGFpbCwgKmxhc3RzZWc7PGJyPg0KLcKg IMKgIMKgIMKgdWludDE2X3QgaGRyX2xlbiwgbDJfbGVuOzxicj4NCi08YnI+DQotwqAgwqAgwqAg wqBpZiAoY21wICZndDsgMCkgezxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdF9oZWFk ID0gaXRlbS0mZ3Q7Zmlyc3RzZWc7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcGt0X3Rh aWwgPSBwa3Q7PGJyPg0KLcKgIMKgIMKgIMKgfSBlbHNlIHs8YnI+DQotwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBwa3RfaGVhZCA9IHBrdDs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3Rf dGFpbCA9IGl0ZW0tJmd0O2ZpcnN0c2VnOzxicj4NCi3CoCDCoCDCoCDCoH08YnI+DQotPGJyPg0K LcKgIMKgIMKgIMKgLyogY2hlY2sgaWYgdGhlIElQdjQgcGFja2V0IGxlbmd0aCBpcyBncmVhdGVy IHRoYW4gdGhlIG1heCB2YWx1ZSAqLzxicj4NCi3CoCDCoCDCoCDCoGhkcl9sZW4gPSBsMl9vZmZz ZXQgKyBwa3RfaGVhZC0mZ3Q7bDJfbGVuICsgcGt0X2hlYWQtJmd0O2wzX2xlbiArPGJyPg0KLcKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgcGt0X2hlYWQtJmd0O2w0X2xlbjs8YnI+DQotwqAgwqAgwqAg wqBsMl9sZW4gPSBsMl9vZmZzZXQgJmd0OyAwID8gcGt0X2hlYWQtJmd0O291dGVyX2wyX2xlbiA6 IHBrdF9oZWFkLSZndDtsMl9sZW47PGJyPg0KLcKgIMKgIMKgIMKgaWYgKHVubGlrZWx5KHBrdF9o ZWFkLSZndDtwa3RfbGVuIC0gbDJfbGVuICsgcGt0X3RhaWwtJmd0O3BrdF9sZW4gLTxicj4NCi3C oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGhkcl9sZW4gJmd0 OyBNQVhfSVBWNF9QS1RfTEVOR1RIKSk8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1 cm4gMDs8YnI+DQotPGJyPg0KLcKgIMKgIMKgIMKgLyogcmVtb3ZlIHRoZSBwYWNrZXQgaGVhZGVy IGZvciB0aGUgdGFpbCBwYWNrZXQgKi88YnI+DQotwqAgwqAgwqAgwqBydGVfcGt0bWJ1Zl9hZGoo cGt0X3RhaWwsIGhkcl9sZW4pOzxicj4NCi08YnI+DQotwqAgwqAgwqAgwqAvKiBjaGFpbiB0d28g cGFja2V0cyB0b2dldGhlciAqLzxicj4NCi3CoCDCoCDCoCDCoGlmIChjbXAgJmd0OyAwKSB7PGJy Pg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaXRlbS0mZ3Q7bGFzdHNlZy0mZ3Q7bmV4dCA9IHBr dDs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpdGVtLSZndDtsYXN0c2VnID0gcnRlX3Br dG1idWZfbGFzdHNlZyhwa3QpOzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8qIHVwZGF0 ZSBJUCBJRCB0byB0aGUgbGFyZ2VyIHZhbHVlICovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgaXRlbS0mZ3Q7aXBfaWQgPSBpcF9pZDs8YnI+DQotwqAgwqAgwqAgwqB9IGVsc2Ugezxicj4N Ci3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGxhc3RzZWcgPSBydGVfcGt0bWJ1Zl9sYXN0c2VnKHBr dCk7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbGFzdHNlZy0mZ3Q7bmV4dCA9IGl0ZW0t Jmd0O2ZpcnN0c2VnOzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW0tJmd0O2ZpcnN0 c2VnID0gcGt0Ozxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8qIHVwZGF0ZSBzZW50X3Nl cSB0byB0aGUgc21hbGxlciB2YWx1ZSAqLzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0 ZW0tJmd0O3NlbnRfc2VxID0gc2VudF9zZXE7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg aXRlbS0mZ3Q7aXBfaWQgPSBpcF9pZDs8YnI+DQotwqAgwqAgwqAgwqB9PGJyPg0KLcKgIMKgIMKg IMKgaXRlbS0mZ3Q7bmJfbWVyZ2VkKys7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoC8qIHVwZGF0 ZSBNQlVGIG1ldGFkYXRhIGZvciB0aGUgbWVyZ2VkIHBhY2tldCAqLzxicj4NCi3CoCDCoCDCoCDC oHBrdF9oZWFkLSZndDtuYl9zZWdzICs9IHBrdF90YWlsLSZndDtuYl9zZWdzOzxicj4NCi3CoCDC oCDCoCDCoHBrdF9oZWFkLSZndDtwa3RfbGVuICs9IHBrdF90YWlsLSZndDtwa3RfbGVuOzxicj4N Ci08YnI+DQotwqAgwqAgwqAgwqByZXR1cm4gMTs8YnI+DQotfTxicj4NCi08YnI+DQotLyo8YnI+ DQotICogQ2hlY2sgaWYgdHdvIFRDUC9JUHY0IHBhY2tldHMgYXJlIG5laWdoYm9ycy48YnI+DQot ICovPGJyPg0KLXN0YXRpYyBpbmxpbmUgaW50PGJyPg0KLWNoZWNrX3NlcV9vcHRpb24oc3RydWN0 IGdyb190Y3A0X2l0ZW0gKml0ZW0sPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc3RydWN0 IHJ0ZV90Y3BfaGRyICp0Y3BoLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90 IHNlbnRfc2VxLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGlwX2lkLDxi cj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IHRjcF9obCw8YnI+DQotwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCB0Y3BfZGwsPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgdWludDE2X3QgbDJfb2Zmc2V0LDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVp bnQ4X3QgaXNfYXRvbWljKTxicj4NCi17PGJyPg0KLcKgIMKgIMKgIMKgc3RydWN0IHJ0ZV9tYnVm ICpwa3Rfb3JpZyA9IGl0ZW0tJmd0O2ZpcnN0c2VnOzxicj4NCi3CoCDCoCDCoCDCoHN0cnVjdCBy dGVfaXB2NF9oZHIgKmlwaF9vcmlnOzxicj4NCi3CoCDCoCDCoCDCoHN0cnVjdCBydGVfdGNwX2hk ciAqdGNwaF9vcmlnOzxicj4NCi3CoCDCoCDCoCDCoHVpbnQxNl90IGxlbiwgdGNwX2hsX29yaWc7 PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoGlwaF9vcmlnID0gKHN0cnVjdCBydGVfaXB2NF9oZHIg KikocnRlX3BrdG1idWZfbXRvZChwa3Rfb3JpZywgY2hhciAqKSArPGJyPg0KLcKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbDJfb2Zmc2V0ICsgcGt0X29yaWctJmd0O2wyX2xlbik7 PGJyPg0KLcKgIMKgIMKgIMKgdGNwaF9vcmlnID0gKHN0cnVjdCBydGVfdGNwX2hkciAqKSgoY2hh ciAqKWlwaF9vcmlnICsgcGt0X29yaWctJmd0O2wzX2xlbik7PGJyPg0KLcKgIMKgIMKgIMKgdGNw X2hsX29yaWcgPSBwa3Rfb3JpZy0mZ3Q7bDRfbGVuOzxicj4NCi08YnI+DQotwqAgwqAgwqAgwqAv KiBDaGVjayBpZiBUQ1Agb3B0aW9uIGZpZWxkcyBlcXVhbCAqLzxicj4NCi3CoCDCoCDCoCDCoGxl biA9IFJURV9NQVgodGNwX2hsLCB0Y3BfaGxfb3JpZykgLSBzaXplb2Yoc3RydWN0IHJ0ZV90Y3Bf aGRyKTs8YnI+DQotwqAgwqAgwqAgwqBpZiAoKHRjcF9obCAhPSB0Y3BfaGxfb3JpZykgfHwgKChs ZW4gJmd0OyAwKSAmYW1wOyZhbXA7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgKG1lbWNtcCh0Y3BoICsgMSwgdGNwaF9vcmlnICsgMSw8YnI+DQot wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBsZW4pICE9IDApKSk8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gMDs8YnI+ DQotPGJyPg0KLcKgIMKgIMKgIMKgLyogRG9uJiMzOTt0IG1lcmdlIHBhY2tldHMgd2hvc2UgREYg Yml0cyBhcmUgZGlmZmVyZW50ICovPGJyPg0KLcKgIMKgIMKgIMKgaWYgKHVubGlrZWx5KGl0ZW0t Jmd0O2lzX2F0b21pYyBeIGlzX2F0b21pYykpPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg cmV0dXJuIDA7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoC8qIGNoZWNrIGlmIHRoZSB0d28gcGFj a2V0cyBhcmUgbmVpZ2hib3JzICovPGJyPg0KLcKgIMKgIMKgIMKgbGVuID0gcGt0X29yaWctJmd0 O3BrdF9sZW4gLSBsMl9vZmZzZXQgLSBwa3Rfb3JpZy0mZ3Q7bDJfbGVuIC08YnI+DQotwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBwa3Rfb3JpZy0mZ3Q7bDNfbGVuIC0gdGNwX2hsX29yaWc7PGJyPg0K LcKgIMKgIMKgIMKgaWYgKChzZW50X3NlcSA9PSBpdGVtLSZndDtzZW50X3NlcSArIGxlbikgJmFt cDsmYW1wOyAoaXNfYXRvbWljIHx8PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgKGlwX2lkID09IGl0ZW0tJmd0O2lwX2lkICsgMSkpKTxicj4NCi3C oCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8qIGFwcGVuZCB0aGUgbmV3IHBhY2tldCAqLzxicj4NCi3C oCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiAxOzxicj4NCi3CoCDCoCDCoCDCoGVsc2UgaWYg KChzZW50X3NlcSArIHRjcF9kbCA9PSBpdGVtLSZndDtzZW50X3NlcSkgJmFtcDsmYW1wOyAoaXNf YXRvbWljIHx8PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgKGlwX2lkICsgaXRlbS0mZ3Q7bmJfbWVyZ2VkID09IGl0ZW0tJmd0O2lwX2lkKSkpPGJy Pg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyogcHJlLXBlbmQgdGhlIG5ldyBwYWNrZXQgKi88 YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gLTE7PGJyPg0KLTxicj4NCi3CoCDC oCDCoCDCoHJldHVybiAwOzxicj4NCi19PGJyPg0KwqAjZW5kaWY8YnI+DQpkaWZmIC0tZ2l0IGEv bGliL2dyby9ncm9fdGNwNi5jIGIvbGliL2dyby9ncm9fdGNwNi5jPGJyPg0KbmV3IGZpbGUgbW9k ZSAxMDA2NDQ8YnI+DQppbmRleCAwMDAwMDAwMDAwLi43YTczOWYyNDcyPGJyPg0KLS0tIC9kZXYv bnVsbDxicj4NCisrKyBiL2xpYi9ncm8vZ3JvX3RjcDYuYzxicj4NCkBAIC0wLDAgKzEsMzg4IEBA PGJyPg0KKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMy1DbGF1c2U8YnI+DQorICog Q29weXJpZ2h0KGMpIDIwMTcgSW50ZWwgQ29ycG9yYXRpb248YnI+DQorICovPGJyPg0KKzxicj4N CisjaW5jbHVkZSAmbHQ7cnRlX21hbGxvYy5oJmd0Ozxicj4NCisjaW5jbHVkZSAmbHQ7cnRlX21i dWYuaCZndDs8YnI+DQorI2luY2x1ZGUgJmx0O3J0ZV9ldGhkZXYuaCZndDs8YnI+DQorPGJyPg0K KyNpbmNsdWRlICZxdW90O2dyb190Y3A2LmgmcXVvdDs8YnI+DQorI2luY2x1ZGUgJnF1b3Q7Z3Jv X3RjcC5oJnF1b3Q7PGJyPg0KKzxicj4NCit2b2lkICo8YnI+DQorZ3JvX3RjcDZfdGJsX2NyZWF0 ZSh1aW50MTZfdCBzb2NrZXRfaWQsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDE2 X3QgbWF4X2Zsb3dfbnVtLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IG1h eF9pdGVtX3Blcl9mbG93KTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IGdyb190Y3A2 X3RibCAqdGJsOzxicj4NCivCoCDCoCDCoCDCoHNpemVfdCBzaXplOzxicj4NCivCoCDCoCDCoCDC oHVpbnQzMl90IGVudHJpZXNfbnVtLCBpOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBlbnRyaWVz X251bSA9IG1heF9mbG93X251bSAqIG1heF9pdGVtX3Blcl9mbG93Ozxicj4NCivCoCDCoCDCoCDC oGVudHJpZXNfbnVtID0gUlRFX01JTihlbnRyaWVzX251bSwgR1JPX1RDUDZfVEJMX01BWF9JVEVN X05VTSk7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGlmIChlbnRyaWVzX251bSA9PSAwKTxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBOVUxMOzxicj4NCis8YnI+DQorwqAgwqAg wqAgwqB0YmwgPSBydGVfem1hbGxvY19zb2NrZXQoX19mdW5jX18sPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc2l6ZW9mKHN0cnVjdCBncm9fdGNwNl90YmwpLDxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoFJURV9DQUNIRV9MSU5FX1NJWkUs PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc29ja2V0X2lkKTs8YnI+ DQorwqAgwqAgwqAgwqBpZiAodGJsID09IE5VTEwpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgcmV0dXJuIE5VTEw7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoHNpemUgPSBzaXplb2Yoc3Ry dWN0IGdyb190Y3BfaXRlbSkgKiBlbnRyaWVzX251bTs8YnI+DQorwqAgwqAgwqAgwqB0YmwtJmd0 O2l0ZW1zID0gcnRlX3ptYWxsb2Nfc29ja2V0KF9fZnVuY19fLDxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoHNpemUsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgUlRFX0NBQ0hFX0xJTkVfU0laRSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBzb2NrZXRfaWQpOzxicj4NCivCoCDCoCDCoCDCoGlmICh0YmwtJmd0 O2l0ZW1zID09IE5VTEwpIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBydGVfZnJlZSh0 YmwpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBOVUxMOzxicj4NCivCoCDC oCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqB0YmwtJmd0O21heF9pdGVtX251bSA9IGVudHJpZXNf bnVtOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBzaXplID0gc2l6ZW9mKHN0cnVjdCBncm9fdGNw Nl9mbG93KSAqIGVudHJpZXNfbnVtOzxicj4NCivCoCDCoCDCoCDCoHRibC0mZ3Q7Zmxvd3MgPSBy dGVfem1hbGxvY19zb2NrZXQoX19mdW5jX18sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgc2l6ZSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBSVEVfQ0FDSEVfTElORV9TSVpFLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoHNvY2tldF9pZCk7PGJyPg0KK8KgIMKgIMKgIMKgaWYgKHRibC0mZ3Q7Zmxvd3MgPT0g TlVMTCkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJ0ZV9mcmVlKHRibC0mZ3Q7aXRl bXMpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJ0ZV9mcmVlKHRibCk7PGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIE5VTEw7PGJyPg0KK8KgIMKgIMKgIMKgfTxicj4N CivCoCDCoCDCoCDCoC8qIElOVkFMSURfQVJSQVlfSU5ERVggaW5kaWNhdGVzIGFuIGVtcHR5IGZs b3cgKi88YnI+DQorwqAgwqAgwqAgwqBmb3IgKGkgPSAwOyBpICZsdDsgZW50cmllc19udW07IGkr Kyk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0YmwtJmd0O2Zsb3dzW2ldLnN0YXJ0X2lu ZGV4ID0gSU5WQUxJRF9BUlJBWV9JTkRFWDs8YnI+DQorwqAgwqAgwqAgwqB0YmwtJmd0O21heF9m bG93X251bSA9IGVudHJpZXNfbnVtOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqByZXR1cm4gdGJs Ozxicj4NCit9PGJyPg0KKzxicj4NCit2b2lkPGJyPg0KK2dyb190Y3A2X3RibF9kZXN0cm95KHZv aWQgKnRibCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBncm9fdGNwNl90YmwgKnRj cF90YmwgPSB0Ymw7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGlmICh0Y3BfdGJsKSB7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcnRlX2ZyZWUodGNwX3RibC0mZ3Q7aXRlbXMpOzxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJ0ZV9mcmVlKHRjcF90YmwtJmd0O2Zsb3dzKTs8YnI+ DQorwqAgwqAgwqAgwqB9PGJyPg0KK8KgIMKgIMKgIMKgcnRlX2ZyZWUodGNwX3RibCk7PGJyPg0K K308YnI+DQorPGJyPg0KK3N0YXRpYyBpbmxpbmUgdWludDMyX3Q8YnI+DQorZmluZF9hbl9lbXB0 eV9pdGVtKHN0cnVjdCBncm9fdGNwNl90YmwgKnRibCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDC oHVpbnQzMl90IGk7PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgbWF4X2l0ZW1fbnVtID0gdGJs LSZndDttYXhfaXRlbV9udW07PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGZvciAoaSA9IDA7IGkg Jmx0OyBtYXhfaXRlbV9udW07IGkrKyk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAo dGJsLSZndDtpdGVtc1tpXS5maXJzdHNlZyA9PSBOVUxMKTxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBpOzxicj4NCivCoCDCoCDCoCDCoHJldHVybiBJTlZB TElEX0FSUkFZX0lOREVYOzxicj4NCit9PGJyPg0KKzxicj4NCitzdGF0aWMgaW5saW5lIHVpbnQz Ml90PGJyPg0KK2ZpbmRfYW5fZW1wdHlfZmxvdyhzdHJ1Y3QgZ3JvX3RjcDZfdGJsICp0YmwpPGJy Pg0KK3s8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBpOzxicj4NCivCoCDCoCDCoCDCoHVpbnQz Ml90IG1heF9mbG93X251bSA9IHRibC0mZ3Q7bWF4X2Zsb3dfbnVtOzxicj4NCis8YnI+DQorwqAg wqAgwqAgwqBmb3IgKGkgPSAwOyBpICZsdDsgbWF4X2Zsb3dfbnVtOyBpKyspPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgaWYgKHRibC0mZ3Q7Zmxvd3NbaV0uc3RhcnRfaW5kZXggPT0gSU5W QUxJRF9BUlJBWV9JTkRFWCk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqByZXR1cm4gaTs8YnI+DQorwqAgwqAgwqAgwqByZXR1cm4gSU5WQUxJRF9BUlJBWV9JTkRFWDs8 YnI+DQorfTxicj4NCis8YnI+DQorc3RhdGljIGlubGluZSB1aW50MzJfdDxicj4NCitpbnNlcnRf bmV3X2l0ZW0oc3RydWN0IGdyb190Y3A2X3RibCAqdGJsLDxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoHN0cnVjdCBydGVfbWJ1ZiAqcGt0LDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oHVpbnQ2NF90IHN0YXJ0X3RpbWUsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDMy X3QgcHJldl9pZHgsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDMyX3Qgc2VudF9z ZXEsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDhfdCBpc19hdG9taWMpPGJyPg0K K3s8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBpdGVtX2lkeDs8YnI+DQorPGJyPg0KK8KgIMKg IMKgIMKgaXRlbV9pZHggPSBmaW5kX2FuX2VtcHR5X2l0ZW0odGJsKTs8YnI+DQorwqAgwqAgwqAg wqBpZiAoaXRlbV9pZHggPT0gSU5WQUxJRF9BUlJBWV9JTkRFWCk8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqByZXR1cm4gSU5WQUxJRF9BUlJBWV9JTkRFWDs8YnI+DQorPGJyPg0KK8KgIMKg IMKgIMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0uZmlyc3RzZWcgPSBwa3Q7PGJyPg0KK8KgIMKg IMKgIMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0ubGFzdHNlZyA9IHJ0ZV9wa3RtYnVmX2xhc3Rz ZWcocGt0KTs8YnI+DQorwqAgwqAgwqAgwqB0YmwtJmd0O2l0ZW1zW2l0ZW1faWR4XS5zdGFydF90 aW1lID0gc3RhcnRfdGltZTs8YnI+DQorwqAgwqAgwqAgwqB0YmwtJmd0O2l0ZW1zW2l0ZW1faWR4 XS5uZXh0X3BrdF9pZHggPSBJTlZBTElEX0FSUkFZX0lOREVYOzxicj4NCivCoCDCoCDCoCDCoHRi bC0mZ3Q7aXRlbXNbaXRlbV9pZHhdLnNlbnRfc2VxID0gc2VudF9zZXE7PGJyPg0KK8KgIMKgIMKg IMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0ubmJfbWVyZ2VkID0gMTs8YnI+DQorwqAgwqAgwqAg wqB0YmwtJmd0O2l0ZW1zW2l0ZW1faWR4XS5pc19hdG9taWMgPSBpc19hdG9taWM7PGJyPg0KK8Kg IMKgIMKgIMKgdGJsLSZndDtpdGVtX251bSsrOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAvKiBp ZiB0aGUgcHJldmlvdXMgcGFja2V0IGV4aXN0cywgY2hhaW4gdGhlbSB0b2dldGhlci4gKi88YnI+ DQorwqAgwqAgwqAgwqBpZiAocHJldl9pZHggIT0gSU5WQUxJRF9BUlJBWV9JTkRFWCkgezxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbXNbaXRlbV9pZHhdLm5leHRfcGt0 X2lkeCA9PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGJsLSZndDtp dGVtc1twcmV2X2lkeF0ubmV4dF9wa3RfaWR4Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oHRibC0mZ3Q7aXRlbXNbcHJldl9pZHhdLm5leHRfcGt0X2lkeCA9IGl0ZW1faWR4Ozxicj4NCivC oCDCoCDCoCDCoH08YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIGl0ZW1faWR4Ozxicj4N Cit9PGJyPg0KKzxicj4NCitzdGF0aWMgaW5saW5lIHVpbnQzMl90PGJyPg0KK2RlbGV0ZV9pdGVt KHN0cnVjdCBncm9fdGNwNl90YmwgKnRibCwgdWludDMyX3QgaXRlbV9pZHgsPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgdWludDMyX3QgcHJldl9pdGVtX2lkeCk8YnI+DQorezxicj4NCivC oCDCoCDCoCDCoHVpbnQzMl90IG5leHRfaWR4ID0gdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0ubmV4 dF9wa3RfaWR4Ozxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAvKiBOVUxMIGluZGljYXRlcyBhbiBl bXB0eSBpdGVtICovPGJyPg0KK8KgIMKgIMKgIMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0uZmly c3RzZWcgPSBOVUxMOzxicj4NCivCoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbV9udW0tLTs8YnI+DQor wqAgwqAgwqAgwqBpZiAocHJldl9pdGVtX2lkeCAhPSBJTlZBTElEX0FSUkFZX0lOREVYKTxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbXNbcHJldl9pdGVtX2lkeF0ubmV4 dF9wa3RfaWR4ID0gbmV4dF9pZHg7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoHJldHVybiBuZXh0 X2lkeDs8YnI+DQorfTxicj4NCis8YnI+DQorc3RhdGljIGlubGluZSB1aW50MzJfdDxicj4NCitp bnNlcnRfbmV3X2Zsb3coc3RydWN0IGdyb190Y3A2X3RibCAqdGJsLDxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHN0cnVjdCB0Y3A2X2Zsb3dfa2V5ICpzcmMsPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgcnRlX2JlMzJfdCB2dGNfZmxvdyw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqB1aW50MzJfdCBpdGVtX2lkeCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCB0 Y3A2X2Zsb3dfa2V5ICpkc3Q7PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgZmxvd19pZHg7PGJy Pg0KKzxicj4NCivCoCDCoCDCoCDCoGZsb3dfaWR4ID0gZmluZF9hbl9lbXB0eV9mbG93KHRibCk7 PGJyPg0KK8KgIMKgIMKgIMKgaWYgKHVubGlrZWx5KGZsb3dfaWR4ID09IElOVkFMSURfQVJSQVlf SU5ERVgpKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBJTlZBTElEX0FSUkFZ X0lOREVYOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBkc3QgPSAmYW1wOyh0YmwtJmd0O2Zsb3dz W2Zsb3dfaWR4XS5rZXkpOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBydGVfZXRoZXJfYWRkcl9j b3B5KCZhbXA7KHNyYy0mZ3Q7ZXRoX3NhZGRyKSwgJmFtcDsoZHN0LSZndDtldGhfc2FkZHIpKTs8 YnI+DQorwqAgwqAgwqAgwqBydGVfZXRoZXJfYWRkcl9jb3B5KCZhbXA7KHNyYy0mZ3Q7ZXRoX2Rh ZGRyKSwgJmFtcDsoZHN0LSZndDtldGhfZGFkZHIpKTs8YnI+DQorwqAgwqAgwqAgwqBtZW1jcHko JmFtcDtkc3QtJmd0O3NyY19hZGRyWzBdLCAmYW1wO3NyYy0mZ3Q7c3JjX2FkZHJbMF0sIHNpemVv Zihkc3QtJmd0O3NyY19hZGRyKSk7PGJyPg0KK8KgIMKgIMKgIMKgbWVtY3B5KCZhbXA7ZHN0LSZn dDtkc3RfYWRkclswXSwgJmFtcDtzcmMtJmd0O2RzdF9hZGRyWzBdLCBzaXplb2YoZHN0LSZndDtk c3RfYWRkcikpOzxicj4NCivCoCDCoCDCoCDCoGRzdC0mZ3Q7cmVjdl9hY2sgPSBzcmMtJmd0O3Jl Y3ZfYWNrOzxicj4NCivCoCDCoCDCoCDCoGRzdC0mZ3Q7c3JjX3BvcnQgPSBzcmMtJmd0O3NyY19w b3J0Ozxicj4NCivCoCDCoCDCoCDCoGRzdC0mZ3Q7ZHN0X3BvcnQgPSBzcmMtJmd0O2RzdF9wb3J0 Ozxicj4NCis8YnI+DQorwqAgwqAgwqAgwqB0YmwtJmd0O2Zsb3dzW2Zsb3dfaWR4XS5zdGFydF9p bmRleCA9IGl0ZW1faWR4Ozxicj4NCivCoCDCoCDCoCDCoHRibC0mZ3Q7Zmxvd19udW0rKzs8YnI+ DQorwqAgwqAgwqAgwqB0YmwtJmd0O2Zsb3dzLSZndDt2dGNfZmxvdyA9IHZ0Y19mbG93Ozxicj4N Cis8YnI+DQorwqAgwqAgwqAgwqByZXR1cm4gZmxvd19pZHg7PGJyPg0KK308YnI+DQorPGJyPg0K Ky8qPGJyPg0KKyAqIHVwZGF0ZSB0aGUgcGFja2V0IGxlbmd0aCBmb3IgdGhlIGZsdXNoZWQgcGFj a2V0Ljxicj4NCisgKi88YnI+DQorc3RhdGljIGlubGluZSB2b2lkPGJyPg0KK3VwZGF0ZV9oZWFk ZXIoc3RydWN0IGdyb190Y3BfaXRlbSAqaXRlbSk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHN0 cnVjdCBydGVfaXB2Nl9oZHIgKmlwdjZfaGRyOzxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBydGVf bWJ1ZiAqcGt0ID0gaXRlbS0mZ3Q7Zmlyc3RzZWc7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGlw djZfaGRyID0gKHN0cnVjdCBydGVfaXB2Nl9oZHIgKikocnRlX3BrdG1idWZfbXRvZChwa3QsIGNo YXIgKikgKzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdC0mZ3Q7 bDJfbGVuKTs8YnI+DQorwqAgwqAgwqAgwqBpcHY2X2hkci0mZ3Q7cGF5bG9hZF9sZW4gPSBydGVf Y3B1X3RvX2JlXzE2KHBrdC0mZ3Q7cGt0X2xlbiAtPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgcGt0LSZndDtsMl9sZW4gLSBwa3QtJmd0O2wzX2xlbik7PGJyPg0KK308 YnI+DQorPGJyPg0KK2ludDMyX3Q8YnI+DQorZ3JvX3RjcDZfcmVhc3NlbWJsZShzdHJ1Y3QgcnRl X21idWYgKnBrdCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzdHJ1Y3QgZ3JvX3RjcDZf dGJsICp0YmwsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDY0X3Qgc3RhcnRfdGlt ZSk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBydGVfZXRoZXJfaGRyICpldGhfaGRy Ozxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBydGVfaXB2Nl9oZHIgKmlwdjZfaGRyOzxicj4NCivC oCDCoCDCoCDCoHN0cnVjdCBydGVfdGNwX2hkciAqdGNwX2hkcjs8YnI+DQorwqAgwqAgwqAgwqB1 aW50MzJfdCBzZW50X3NlcTs8YnI+DQorwqAgwqAgwqAgwqBpbnQzMl90IHRjcF9kbDs8YnI+DQor wqAgwqAgwqAgwqB1aW50MTZfdCBpcF90bGVuOzxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCB0Y3A2 X2Zsb3dfa2V5IGtleTs8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBjdXJfaWR4LCBwcmV2X2lk eCwgaXRlbV9pZHg7PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgaSwgbWF4X2Zsb3dfbnVtLCBy ZW1haW5pbmdfZmxvd19udW07PGJyPg0KK8KgIMKgIMKgIMKgaW50IGNtcDs8YnI+DQorwqAgwqAg wqAgwqB1aW50OF90IGZpbmQ7PGJyPg0KK8KgIMKgIMKgIMKgcnRlX2JlMzJfdCB2dGNfZmxvd19k aWZmOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAvKjxicj4NCivCoCDCoCDCoCDCoCAqIERvbiYj Mzk7dCBwcm9jZXNzIHRoZSBwYWNrZXQgd2hvc2UgVENQIGhlYWRlciBsZW5ndGggaXMgZ3JlYXRl cjxicj4NCivCoCDCoCDCoCDCoCAqIHRoYW4gNjAgYnl0ZXMgb3IgbGVzcyB0aGFuIDIwIGJ5dGVz Ljxicj4NCivCoCDCoCDCoCDCoCAqLzxicj4NCivCoCDCoCDCoCDCoGlmICh1bmxpa2VseShJTlZB TElEX1RDUF9IRFJMRU4ocGt0LSZndDtsNF9sZW4pKSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqByZXR1cm4gLTE7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGV0aF9oZHIgPSBydGVfcGt0 bWJ1Zl9tdG9kKHBrdCwgc3RydWN0IHJ0ZV9ldGhlcl9oZHIgKik7PGJyPg0KK8KgIMKgIMKgIMKg aXB2Nl9oZHIgPSAoc3RydWN0IHJ0ZV9pcHY2X2hkciAqKSgoY2hhciAqKWV0aF9oZHIgKyBwa3Qt Jmd0O2wyX2xlbik7PGJyPg0KK8KgIMKgIMKgIMKgdGNwX2hkciA9IChzdHJ1Y3QgcnRlX3RjcF9o ZHIgKikoKGNoYXIgKilpcHY2X2hkciArIHBrdC0mZ3Q7bDNfbGVuKTs8YnI+DQorPGJyPg0KK8Kg IMKgIMKgIMKgLyo8YnI+DQorwqAgwqAgwqAgwqAgKiBEb24mIzM5O3QgcHJvY2VzcyB0aGUgcGFj a2V0IHdoaWNoIGhhcyBGSU4sIFNZTiwgUlNULCBQU0gsIFVSRywgRUNFPGJyPg0KK8KgIMKgIMKg IMKgICogb3IgQ1dSIHNldC48YnI+DQorwqAgwqAgwqAgwqAgKi88YnI+DQorwqAgwqAgwqAgwqBp ZiAodGNwX2hkci0mZ3Q7dGNwX2ZsYWdzICE9IFJURV9UQ1BfQUNLX0ZMQUcpPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIC0xOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBpcF90 bGVuID0gcnRlX2JlX3RvX2NwdV8xNihpcHY2X2hkci0mZ3Q7cGF5bG9hZF9sZW4pOzxicj4NCivC oCDCoCDCoCDCoC8qIDxicj4NCivCoCDCoCDCoCDCoCAqIFRyaW0gdGhlIHRhaWwgcGFkZGluZyBi eXRlcy4gVGhlIElQdjYgaGVhZGVyIGlzIGZpeGVkIHRvIDxicj4NCivCoCDCoCDCoCDCoCAqIDQw IGJ5dGVzIHVubGlrZSBJUHY0IHRoYXQgaXMgdmFyaWFibGUuIFRoZSBsZW5ndGggaW4gdGhlIElQ djYgaGVhZGVyIDxicj4NCivCoCDCoCDCoCDCoCAqIGNvbnRhaW5zIG9ubHkgbGVuZ3RoIG9mIFRD UCBIZWFkZXIgKyBUQ1AgUGF5bG9hZCwgd2hlcmVhcyBJUHY0IGhlYWRlciBjb250YWlucyA8YnI+ DQorwqAgwqAgwqAgwqAgKiBsZW5ndGggb2YgSVAgSGVhZGVyICsgVENQIEhlYWRlciArIFRDUCBQ YXlsb2FkPGJyPg0KK8KgIMKgIMKgIMKgICovPGJyPg0KK8KgIMKgIMKgIMKgaWYgKHBrdC0mZ3Q7 cGt0X2xlbiAmZ3Q7ICh1aW50MzJfdCkoaXBfdGxlbiArIHBrdC0mZ3Q7bDJfbGVuICsgcGt0LSZn dDtsM19sZW4pKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJ0ZV9wa3RtYnVmX3RyaW0o cGt0LCBwa3QtJmd0O3BrdF9sZW4gLSBpcF90bGVuIC0gcGt0LSZndDtsMl9sZW4gLSBwa3QtJmd0 O2wzX2xlbik7PGJyPg0KK8KgIMKgIMKgIMKgLyo8YnI+DQorwqAgwqAgwqAgwqAgKiBEb24mIzM5 O3QgcHJvY2VzcyB0aGUgcGFja2V0IHdob3NlIHBheWxvYWQgbGVuZ3RoIGlzIGxlc3MgdGhhbiBv cjxicj4NCivCoCDCoCDCoCDCoCAqIGVxdWFsIHRvIDAuPGJyPg0KK8KgIMKgIMKgIMKgICovPGJy Pg0KK8KgIMKgIMKgIMKgdGNwX2RsID0gaXBfdGxlbiAtIHBrdC0mZ3Q7bDRfbGVuOzxicj4NCivC oCDCoCDCoCDCoGlmICh0Y3BfZGwgJmx0Oz0gMCk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqByZXR1cm4gLTE7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoHNlbnRfc2VxID0gcnRlX2JlX3Rv X2NwdV8zMih0Y3BfaGRyLSZndDtzZW50X3NlcSk7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoHJ0 ZV9ldGhlcl9hZGRyX2NvcHkoJmFtcDsoZXRoX2hkci0mZ3Q7c3JjX2FkZHIpLCAmYW1wOyhrZXku ZXRoX3NhZGRyKSk7PGJyPg0KK8KgIMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJfY29weSgmYW1wOyhl dGhfaGRyLSZndDtkc3RfYWRkciksICZhbXA7KGtleS5ldGhfZGFkZHIpKTs8YnI+DQorwqAgwqAg bWVtY3B5KCZhbXA7a2V5LnNyY19hZGRyWzBdLCAmYW1wO2lwdjZfaGRyLSZndDtzcmNfYWRkciwg c2l6ZW9mKGtleS5zcmNfYWRkcikpOzxicj4NCivCoCDCoCBtZW1jcHkoJmFtcDtrZXkuZHN0X2Fk ZHJbMF0sICZhbXA7aXB2Nl9oZHItJmd0O2RzdF9hZGRyLCBzaXplb2Yoa2V5LmRzdF9hZGRyKSk7 PGJyPg0KK8KgIMKgIMKgIMKga2V5LnNyY19wb3J0ID0gdGNwX2hkci0mZ3Q7c3JjX3BvcnQ7PGJy Pg0KK8KgIMKgIMKgIMKga2V5LmRzdF9wb3J0ID0gdGNwX2hkci0mZ3Q7ZHN0X3BvcnQ7PGJyPg0K K8KgIMKgIMKgIMKga2V5LnJlY3ZfYWNrID0gdGNwX2hkci0mZ3Q7cmVjdl9hY2s7PGJyPg0KKzxi cj4NCivCoCDCoCDCoCDCoC8qIFNlYXJjaCBmb3IgYSBtYXRjaGVkIGZsb3cuICovPGJyPg0KK8Kg IMKgIMKgIMKgbWF4X2Zsb3dfbnVtID0gdGJsLSZndDttYXhfZmxvd19udW07PGJyPg0KK8KgIMKg IMKgIMKgcmVtYWluaW5nX2Zsb3dfbnVtID0gdGJsLSZndDtmbG93X251bTs8YnI+DQorwqAgwqAg wqAgwqBmaW5kID0gMDs8YnI+DQorwqAgwqAgwqAgwqBmb3IgKGkgPSAwOyBpICZsdDsgbWF4X2Zs b3dfbnVtICZhbXA7JmFtcDsgcmVtYWluaW5nX2Zsb3dfbnVtOyBpKyspIHs8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBpZiAodGJsLSZndDtmbG93c1tpXS5zdGFydF9pbmRleCAhPSBJTlZB TElEX0FSUkFZX0lOREVYKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgaWYgKGlzX3NhbWVfdGNwNl9mbG93KHRibC0mZ3Q7Zmxvd3NbaV0ua2V5LCBrZXkpKSB7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyogPGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICogSVAg dmVyc2lvbiAoNCkgVHJhZmZpYyBDbGFzcyAoOCkgRmxvdyBMYWJlbCAoMjApIDxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqIEFsbCBmaWVsZHMg ZXhjZXB0IFRyYWZmaWMgY2xhc3Mgc2hvdWxkIGJlIHNhbWU8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAqLzxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHZ0Y19mbG93X2RpZmYgPSAoaXB2Nl9oZHIt Jmd0O3Z0Y19mbG93IF4gdGJsLSZndDtmbG93cy0mZ3Q7dnRjX2Zsb3cpOzxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmICh2dGNfZmxvd19kaWZm ICZhbXA7IGh0b25sKDB4RjAwRkZGRkYpKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgY29udGludWU7PGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfTxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGZpbmQgPSAxOzxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGJyZWFrOzxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZW1haW5pbmdfZmxvd19udW0tLTs8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0KK8KgIMKgIMKgIMKgfTxicj4NCis8YnI+DQorwqAgwqAg wqAgwqAvKjxicj4NCivCoCDCoCDCoCDCoCAqIEZhaWwgdG8gZmluZCBhIG1hdGNoZWQgZmxvdy4g SW5zZXJ0IGEgbmV3IGZsb3cgYW5kIHN0b3JlIHRoZTxicj4NCivCoCDCoCDCoCDCoCAqIHBhY2tl dCBpbnRvIHRoZSBmbG93Ljxicj4NCivCoCDCoCDCoCDCoCAqLzxicj4NCivCoCDCoCDCoCDCoGlm IChmaW5kID09IDApIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpdGVtX2lkeCA9IGlu c2VydF9uZXdfaXRlbSh0YmwsIHBrdCwgc3RhcnRfdGltZSw8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBJTlZBTElEX0FSUkFZX0lOREVYLCBzZW50 X3NlcSwgdHJ1ZSk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGl0ZW1faWR4ID09 IElOVkFMSURfQVJSQVlfSU5ERVgpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgcmV0dXJuIC0xOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChpbnNlcnRf bmV3X2Zsb3codGJsLCAmYW1wO2tleSwgaXB2Nl9oZHItJmd0O3Z0Y19mbG93LCBpdGVtX2lkeCkg PT08YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBJ TlZBTElEX0FSUkFZX0lOREVYKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgLyo8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKiBGYWls IHRvIGluc2VydCBhIG5ldyBmbG93LCBzbyBkZWxldGUgdGhlPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgICogc3RvcmVkIHBhY2tldC48YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBkZWxldGVfaXRlbSh0YmwsIGl0ZW1faWR4LCBJTlZBTElEX0FSUkFZX0lOREVY KTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gLTE7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oHJldHVybiAwOzxicj4NCivCoCDCoCDCoCDCoH08YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgLyo8 YnI+DQorwqAgwqAgwqAgwqAgKiBDaGVjayBhbGwgcGFja2V0cyBpbiB0aGUgZmxvdyBhbmQgdHJ5 IHRvIGZpbmQgYSBuZWlnaGJvciBmb3I8YnI+DQorwqAgwqAgwqAgwqAgKiB0aGUgaW5wdXQgcGFj a2V0Ljxicj4NCivCoCDCoCDCoCDCoCAqLzxicj4NCivCoCDCoCDCoCDCoGN1cl9pZHggPSB0Ymwt Jmd0O2Zsb3dzW2ldLnN0YXJ0X2luZGV4Ozxicj4NCivCoCDCoCDCoCDCoHByZXZfaWR4ID0gY3Vy X2lkeDs8YnI+DQorwqAgwqAgwqAgwqBkbyB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg Y21wID0gY2hlY2tfc2VxX29wdGlvbigmYW1wOyh0YmwtJmd0O2l0ZW1zW2N1cl9pZHhdKSwgdGNw X2hkciw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBzZW50X3NlcSwgMCwgcGt0LSZndDtsNF9sZW4sIHRjcF9kbCwgMCw8YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0cnVlKTs8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBpZiAoY21wKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgaWYgKG1lcmdlX3R3b190Y3BfcGFja2V0cygmYW1wOyh0YmwtJmd0O2l0ZW1z W2N1cl9pZHhdKSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3QsIGNtcCwgc2VudF9zZXEsIDAsIDAp KSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg cmV0dXJuIDE7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIH08YnI+DQorPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyo8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgKiBGYWlsIHRvIG1lcmdlIHRoZSB0d28gcGFja2V0cywgYXMgdGhlIHBh Y2tldDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqIGxlbmd0aCBp cyBncmVhdGVyIHRoYW4gdGhlIG1heCB2YWx1ZS4gU3RvcmU8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgKiB0aGUgcGFja2V0IGludG8gdGhlIGZsb3cuPGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICovPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGluc2VydF9uZXdfaXRlbSh0YmwsIHBrdCwgc3RhcnRf dGltZSwgY3VyX2lkeCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzZW50X3NlcSwgdHJ1ZSkgPT08YnI+ DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBJTlZBTElEX0FSUkFZX0lOREVYKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiAtMTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gMDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9 PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcHJldl9pZHggPSBjdXJfaWR4Ozxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoGN1cl9pZHggPSB0YmwtJmd0O2l0ZW1zW2N1cl9pZHhdLm5l eHRfcGt0X2lkeDs8YnI+DQorwqAgwqAgwqAgwqB9IHdoaWxlIChjdXJfaWR4ICE9IElOVkFMSURf QVJSQVlfSU5ERVgpOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAvKiBGYWlsIHRvIGZpbmQgYSBu ZWlnaGJvciwgc28gc3RvcmUgdGhlIHBhY2tldCBpbnRvIHRoZSBmbG93LiAqLzxicj4NCivCoCDC oCDCoCDCoGlmIChpbnNlcnRfbmV3X2l0ZW0odGJsLCBwa3QsIHN0YXJ0X3RpbWUsIHByZXZfaWR4 LCBzZW50X3NlcSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqB0cnVlKSA9PSBJTlZBTElEX0FSUkFZX0lOREVYKTxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoHJldHVybiAtMTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIDA7PGJy Pg0KK308YnI+DQorPGJyPg0KK3VpbnQxNl90PGJyPg0KK2dyb190Y3A2X3RibF90aW1lb3V0X2Zs dXNoKHN0cnVjdCBncm9fdGNwNl90YmwgKnRibCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqB1aW50NjRfdCBmbHVzaF90aW1lc3RhbXAsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg c3RydWN0IHJ0ZV9tYnVmICoqb3V0LDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQx Nl90IG5iX291dCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHVpbnQxNl90IGsgPSAwOzxicj4N CivCoCDCoCDCoCDCoHVpbnQzMl90IGksIGo7PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgbWF4 X2Zsb3dfbnVtID0gdGJsLSZndDttYXhfZmxvd19udW07PGJyPg0KKzxicj4NCivCoCDCoCDCoCDC oGZvciAoaSA9IDA7IGkgJmx0OyBtYXhfZmxvd19udW07IGkrKykgezxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoGlmICh1bmxpa2VseSh0YmwtJmd0O2Zsb3dfbnVtID09IDApKTxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBrOzxicj4NCis8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBqID0gdGJsLSZndDtmbG93c1tpXS5zdGFydF9pbmRleDs8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB3aGlsZSAoaiAhPSBJTlZBTElEX0FSUkFZX0lO REVYKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKHRibC0m Z3Q7aXRlbXNbal0uc3RhcnRfdGltZSAmbHQ7PSBmbHVzaF90aW1lc3RhbXApIHs8YnI+DQorwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBvdXRbaysrXSA9IHRi bC0mZ3Q7aXRlbXNbal0uZmlyc3RzZWc7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKHRibC0mZ3Q7aXRlbXNbal0ubmJfbWVyZ2VkICZndDsg MSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqB1cGRhdGVfaGVhZGVyKCZhbXA7KHRibC0mZ3Q7aXRlbXNbal0pKTs8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKjxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqIERlbGV0ZSB0 aGUgcGFja2V0IGFuZCBnZXQgdGhlIG5leHQ8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKiBwYWNrZXQgaW4gdGhlIGZsb3cuPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICovPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaiA9IGRlbGV0ZV9pdGVt KHRibCwgaiwgSU5WQUxJRF9BUlJBWV9JTkRFWCk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGJsLSZndDtmbG93c1tpXS5zdGFydF9pbmRleCA9 IGo7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg aWYgKGogPT0gSU5WQUxJRF9BUlJBWV9JTkRFWCk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0YmwtJmd0O2Zsb3dfbnVtLS07 PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoGlmICh1bmxpa2VseShrID09IG5iX291dCkpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIGs7PGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfSBlbHNlPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyo8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKiBUaGUgbGVmdCBwYWNrZXRzIGlu IHRoaXMgZmxvdyB3b24mIzM5O3QgYmU8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgKiB0aW1lb3V0LiBHbyB0byBjaGVjayBvdGhlciBmbG93cy48 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKi88 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBicmVh azs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0KK8KgIMKgIMKgIMKgfTxicj4N CivCoCDCoCDCoCDCoHJldHVybiBrOzxicj4NCit9PGJyPg0KKzxicj4NCit1aW50MzJfdDxicj4N Citncm9fdGNwNl90YmxfcGt0X2NvdW50KHZvaWQgKnRibCk8YnI+DQorezxicj4NCivCoCDCoCDC oCDCoHN0cnVjdCBncm9fdGNwNl90YmwgKmdyb190YmwgPSB0Ymw7PGJyPg0KKzxicj4NCivCoCDC oCDCoCDCoGlmIChncm9fdGJsKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBn cm9fdGJsLSZndDtpdGVtX251bTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIDA7PGJy Pg0KK308YnI+DQpkaWZmIC0tZ2l0IGEvbGliL2dyby9ncm9fdGNwNi5oIGIvbGliL2dyby9ncm9f dGNwNi5oPGJyPg0KbmV3IGZpbGUgbW9kZSAxMDA2NDQ8YnI+DQppbmRleCAwMDAwMDAwMDAwLi5h ZWEyMzFhZGJiPGJyPg0KLS0tIC9kZXYvbnVsbDxicj4NCisrKyBiL2xpYi9ncm8vZ3JvX3RjcDYu aDxicj4NCkBAIC0wLDAgKzEsMTUwIEBAPGJyPg0KKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVy OiBCU0QtMy1DbGF1c2U8YnI+DQorICogQ29weXJpZ2h0KGMpIDIwMTcgSW50ZWwgQ29ycG9yYXRp b248YnI+DQorICovPGJyPg0KKzxicj4NCisjaWZuZGVmIF9HUk9fVENQNl9IXzxicj4NCisjZGVm aW5lIF9HUk9fVENQNl9IXzxicj4NCis8YnI+DQorI2RlZmluZSBJTlZBTElEX0FSUkFZX0lOREVY IDB4ZmZmZmZmZmZVTDxicj4NCisjZGVmaW5lIEdST19UQ1A2X1RCTF9NQVhfSVRFTV9OVU0gKDEw MjRVTCAqIDEwMjRVTCk8YnI+DQorPGJyPg0KKy8qIEhlYWRlciBmaWVsZHMgcmVwcmVzZW50aW5n IGEgVENQL0lQdjYgZmxvdyAqLzxicj4NCitzdHJ1Y3QgdGNwNl9mbG93X2tleSB7PGJyPg0KK8Kg IMKgIMKgIMKgc3RydWN0IHJ0ZV9ldGhlcl9hZGRyIGV0aF9zYWRkcjs8YnI+DQorwqAgwqAgwqAg wqBzdHJ1Y3QgcnRlX2V0aGVyX2FkZHIgZXRoX2RhZGRyOzxicj4NCivCoCDCoCB1aW50OF90wqAg c3JjX2FkZHJbMTZdOzxicj4NCivCoCDCoCB1aW50OF90wqAgZHN0X2FkZHJbMTZdOzxicj4NCis8 YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCByZWN2X2Fjazs8YnI+DQorwqAgwqAgwqAgwqB1aW50 MTZfdCBzcmNfcG9ydDs8YnI+DQorwqAgwqAgwqAgwqB1aW50MTZfdCBkc3RfcG9ydDs8YnI+DQor fTs8YnI+DQorPGJyPg0KK3N0cnVjdCBncm9fdGNwNl9mbG93IHs8YnI+DQorwqAgwqAgwqAgwqBz dHJ1Y3QgdGNwNl9mbG93X2tleSBrZXk7PGJyPg0KK8KgIMKgIMKgIMKgcnRlX2JlMzJfdCB2dGNf Zmxvdzs8YnI+DQorwqAgwqAgwqAgwqAvKjxicj4NCivCoCDCoCDCoCDCoCAqIFRoZSBpbmRleCBv ZiB0aGUgZmlyc3QgcGFja2V0IGluIHRoZSBmbG93Ljxicj4NCivCoCDCoCDCoCDCoCAqIElOVkFM SURfQVJSQVlfSU5ERVggaW5kaWNhdGVzIGFuIGVtcHR5IGZsb3cuPGJyPg0KK8KgIMKgIMKgIMKg ICovPGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3Qgc3RhcnRfaW5kZXg7PGJyPg0KK307PGJyPg0K Kzxicj4NCisvKjxicj4NCisgKiBUQ1AvSVB2NiByZWFzc2VtYmx5IHRhYmxlIHN0cnVjdHVyZS48 YnI+DQorICovPGJyPg0KK3N0cnVjdCBncm9fdGNwNl90Ymwgezxicj4NCivCoCDCoCDCoCDCoC8q IGl0ZW0gYXJyYXkgKi88YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgZ3JvX3RjcF9pdGVtICppdGVt czs8YnI+DQorwqAgwqAgwqAgwqAvKiBmbG93IGFycmF5ICovPGJyPg0KK8KgIMKgIMKgIMKgc3Ry dWN0IGdyb190Y3A2X2Zsb3cgKmZsb3dzOzxicj4NCivCoCDCoCDCoCDCoC8qIGN1cnJlbnQgaXRl bSBudW1iZXIgKi88YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBpdGVtX251bTs8YnI+DQorwqAg wqAgwqAgwqAvKiBjdXJyZW50IGZsb3cgbnVtICovPGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3Qg Zmxvd19udW07PGJyPg0KK8KgIMKgIMKgIMKgLyogaXRlbSBhcnJheSBzaXplICovPGJyPg0KK8Kg IMKgIMKgIMKgdWludDMyX3QgbWF4X2l0ZW1fbnVtOzxicj4NCivCoCDCoCDCoCDCoC8qIGZsb3cg YXJyYXkgc2l6ZSAqLzxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IG1heF9mbG93X251bTs8YnI+ DQorfTs8YnI+DQorPGJyPg0KKy8qKjxicj4NCisgKiBUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgYSBU Q1AvSVB2NiByZWFzc2VtYmx5IHRhYmxlLjxicj4NCisgKjxicj4NCisgKiBAcGFyYW0gc29ja2V0 X2lkPGJyPg0KKyAqwqAgU29ja2V0IGluZGV4IGZvciBhbGxvY2F0aW5nIHRoZSBUQ1AvSVB2NiBy ZWFzc2VtYmxlIHRhYmxlPGJyPg0KKyAqIEBwYXJhbSBtYXhfZmxvd19udW08YnI+DQorICrCoCBU aGUgbWF4aW11bSBudW1iZXIgb2YgZmxvd3MgaW4gdGhlIFRDUC9JUHY2IEdSTyB0YWJsZTxicj4N CisgKiBAcGFyYW0gbWF4X2l0ZW1fcGVyX2Zsb3c8YnI+DQorICrCoCBUaGUgbWF4aW11bSBudW1i ZXIgb2YgcGFja2V0cyBwZXIgZmxvdzxicj4NCisgKjxicj4NCisgKiBAcmV0dXJuPGJyPg0KKyAq wqAgLSBSZXR1cm4gdGhlIHRhYmxlIHBvaW50ZXIgb24gc3VjY2Vzcy48YnI+DQorICrCoCAtIFJl dHVybiBOVUxMIG9uIGZhaWx1cmUuPGJyPg0KKyAqLzxicj4NCit2b2lkICpncm9fdGNwNl90Ymxf Y3JlYXRlKHVpbnQxNl90IHNvY2tldF9pZCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1 aW50MTZfdCBtYXhfZmxvd19udW0sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDE2 X3QgbWF4X2l0ZW1fcGVyX2Zsb3cpOzxicj4NCis8YnI+DQorLyoqPGJyPg0KKyAqIFRoaXMgZnVu Y3Rpb24gZGVzdHJveXMgYSBUQ1AvSVB2NiByZWFzc2VtYmx5IHRhYmxlLjxicj4NCisgKjxicj4N CisgKiBAcGFyYW0gdGJsPGJyPg0KKyAqwqAgUG9pbnRlciBwb2ludGluZyB0byB0aGUgVENQL0lQ djYgcmVhc3NlbWJseSB0YWJsZS48YnI+DQorICovPGJyPg0KK3ZvaWQgZ3JvX3RjcDZfdGJsX2Rl c3Ryb3kodm9pZCAqdGJsKTs8YnI+DQorPGJyPg0KKy8qKjxicj4NCisgKiBUaGlzIGZ1bmN0aW9u IG1lcmdlcyBhIFRDUC9JUHY2IHBhY2tldC4gSXQgZG9lc24mIzM5O3QgcHJvY2VzcyB0aGUgcGFj a2V0LDxicj4NCisgKiB3aGljaCBoYXMgU1lOLCBGSU4sIFJTVCwgUFNILCBDV1IsIEVDRSBvciBV Ukcgc2V0LCBvciBkb2VzbiYjMzk7dCBoYXZlPGJyPg0KKyAqIHBheWxvYWQuPGJyPg0KKyAqPGJy Pg0KKyAqIFRoaXMgZnVuY3Rpb24gZG9lc24mIzM5O3QgY2hlY2sgaWYgdGhlIHBhY2tldCBoYXMg Y29ycmVjdCBjaGVja3N1bXMgYW5kPGJyPg0KKyAqIGRvZXNuJiMzOTt0IHJlLWNhbGN1bGF0ZSBj aGVja3N1bXMgZm9yIHRoZSBtZXJnZWQgcGFja2V0LiBBZGRpdGlvbmFsbHksPGJyPg0KKyAqIGl0 IGFzc3VtZXMgdGhlIHBhY2tldHMgYXJlIGNvbXBsZXRlIChpLmUuLCBNRj09MCAmYW1wOyZhbXA7 IGZyYWdfb2ZmPT0wKSw8YnI+DQorICogd2hlbiBJUCBmcmFnbWVudGF0aW9uIGlzIHBvc3NpYmxl IChpLmUuLCBERj09MCkuIEl0IHJldHVybnMgdGhlPGJyPg0KKyAqIHBhY2tldCwgaWYgdGhlIHBh Y2tldCBoYXMgaW52YWxpZCBwYXJhbWV0ZXJzIChlLmcuIFNZTiBiaXQgaXMgc2V0KTxicj4NCisg KiBvciB0aGVyZSBpcyBubyBhdmFpbGFibGUgc3BhY2UgaW4gdGhlIHRhYmxlLjxicj4NCisgKjxi cj4NCisgKiBAcGFyYW0gcGt0PGJyPg0KKyAqwqAgUGFja2V0IHRvIHJlYXNzZW1ibGU8YnI+DQor ICogQHBhcmFtIHRibDxicj4NCisgKsKgIFBvaW50ZXIgcG9pbnRpbmcgdG8gdGhlIFRDUC9JUHY2 IHJlYXNzZW1ibHkgdGFibGU8YnI+DQorICogQHN0YXJ0X3RpbWU8YnI+DQorICrCoCBUaGUgdGlt ZSB3aGVuIHRoZSBwYWNrZXQgaXMgaW5zZXJ0ZWQgaW50byB0aGUgdGFibGU8YnI+DQorICo8YnI+ DQorICogQHJldHVybjxicj4NCisgKsKgIC0gUmV0dXJuIGEgcG9zaXRpdmUgdmFsdWUgaWYgdGhl IHBhY2tldCBpcyBtZXJnZWQuPGJyPg0KKyAqwqAgLSBSZXR1cm4gemVybyBpZiB0aGUgcGFja2V0 IGlzbiYjMzk7dCBtZXJnZWQgYnV0IHN0b3JlZCBpbiB0aGUgdGFibGUuPGJyPg0KKyAqwqAgLSBS ZXR1cm4gYSBuZWdhdGl2ZSB2YWx1ZSBmb3IgaW52YWxpZCBwYXJhbWV0ZXJzIG9yIG5vIGF2YWls YWJsZTxicj4NCisgKsKgIMKgIHNwYWNlIGluIHRoZSB0YWJsZS48YnI+DQorICovPGJyPg0KK2lu dDMyX3QgZ3JvX3RjcDZfcmVhc3NlbWJsZShzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQorwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqBzdHJ1Y3QgZ3JvX3RjcDZfdGJsICp0YmwsPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgdWludDY0X3Qgc3RhcnRfdGltZSk7PGJyPg0KKzxicj4NCisvKio8 YnI+DQorICogVGhpcyBmdW5jdGlvbiBmbHVzaGVzIHRpbWVvdXQgcGFja2V0cyBpbiBhIFRDUC9J UHY0IHJlYXNzZW1ibHkgdGFibGUsPGJyPg0KKyAqIGFuZCB3aXRob3V0IHVwZGF0aW5nIGNoZWNr c3Vtcy48YnI+DQorICo8YnI+DQorICogQHBhcmFtIHRibDxicj4NCisgKsKgIFRDUC9JUHY0IHJl YXNzZW1ibHkgdGFibGUgcG9pbnRlcjxicj4NCisgKiBAcGFyYW0gZmx1c2hfdGltZXN0YW1wPGJy Pg0KKyAqwqAgRmx1c2ggcGFja2V0cyB3aGljaCBhcmUgaW5zZXJ0ZWQgaW50byB0aGUgdGFibGUg YmVmb3JlIG9yIGF0IHRoZTxicj4NCisgKsKgIGZsdXNoX3RpbWVzdGFtcC48YnI+DQorICogQHBh cmFtIG91dDxicj4NCisgKsKgIFBvaW50ZXIgYXJyYXkgdXNlZCB0byBrZWVwIGZsdXNoZWQgcGFj a2V0czxicj4NCisgKiBAcGFyYW0gbmJfb3V0PGJyPg0KKyAqwqAgVGhlIGVsZW1lbnQgbnVtYmVy IGluICYjMzk7b3V0JiMzOTsuIEl0IGFsc28gZGV0ZXJtaW5lcyB0aGUgbWF4aW11bSBudW1iZXIg b2Y8YnI+DQorICrCoCBwYWNrZXRzIHRoYXQgY2FuIGJlIGZsdXNoZWQgZmluYWxseS48YnI+DQor ICo8YnI+DQorICogQHJldHVybjxicj4NCisgKsKgIFRoZSBudW1iZXIgb2YgZmx1c2hlZCBwYWNr ZXRzPGJyPg0KKyAqLzxicj4NCit1aW50MTZfdCBncm9fdGNwNl90YmxfdGltZW91dF9mbHVzaChz dHJ1Y3QgZ3JvX3RjcDZfdGJsICp0YmwsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWlu dDY0X3QgZmx1c2hfdGltZXN0YW1wLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHN0cnVj dCBydGVfbWJ1ZiAqKm91dCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCBu Yl9vdXQpOzxicj4NCis8YnI+DQorLyoqPGJyPg0KKyAqIFRoaXMgZnVuY3Rpb24gcmV0dXJucyB0 aGUgbnVtYmVyIG9mIHRoZSBwYWNrZXRzIGluIGEgVENQL0lQdjQ8YnI+DQorICogcmVhc3NlbWJs eSB0YWJsZS48YnI+DQorICo8YnI+DQorICogQHBhcmFtIHRibDxicj4NCisgKsKgIFRDUC9JUHY0 IHJlYXNzZW1ibHkgdGFibGUgcG9pbnRlcjxicj4NCisgKjxicj4NCisgKiBAcmV0dXJuPGJyPg0K KyAqwqAgVGhlIG51bWJlciBvZiBwYWNrZXRzIGluIHRoZSB0YWJsZTxicj4NCisgKi88YnI+DQor dWludDMyX3QgZ3JvX3RjcDZfdGJsX3BrdF9jb3VudCh2b2lkICp0YmwpOzxicj4NCis8YnI+DQor Lyo8YnI+DQorICogQ2hlY2sgaWYgdHdvIFRDUC9JUHY0IHBhY2tldHMgYmVsb25nIHRvIHRoZSBz YW1lIGZsb3cuPGJyPg0KKyAqLzxicj4NCitzdGF0aWMgaW5saW5lIGludDxicj4NCitpc19zYW1l X3RjcDZfZmxvdyhzdHJ1Y3QgdGNwNl9mbG93X2tleSBrMSwgc3RydWN0IHRjcDZfZmxvd19rZXkg azIpPGJyPg0KK3s8YnI+DQorwqAgwqAgcmV0dXJuICghbWVtY21wKCZhbXA7azEsICZhbXA7azIs IHNpemVvZihzdHJ1Y3QgdGNwNl9mbG93X2tleSkpKTs8YnI+DQorfTxicj4NCis8YnI+DQorI2Vu ZGlmPGJyPg0KXCBObyBuZXdsaW5lIGF0IGVuZCBvZiBmaWxlPGJyPg0KZGlmZiAtLWdpdCBhL2xp Yi9ncm8vZ3JvX3Z4bGFuX3RjcDQuYyBiL2xpYi9ncm8vZ3JvX3Z4bGFuX3RjcDQuYzxicj4NCmlu ZGV4IDNiZTRkZWI3YzcuLjU2YjMwYjhjOTggMTAwNjQ0PGJyPg0KLS0tIGEvbGliL2dyby9ncm9f dnhsYW5fdGNwNC5jPGJyPg0KKysrIGIvbGliL2dyby9ncm9fdnhsYW5fdGNwNC5jPGJyPg0KQEAg LTcsNiArNyw3IEBAPGJyPg0KwqAjaW5jbHVkZSAmbHQ7cnRlX2V0aGRldi5oJmd0Ozxicj4NCsKg I2luY2x1ZGUgJmx0O3J0ZV91ZHAuaCZndDs8YnI+DQo8YnI+DQorI2luY2x1ZGUgJnF1b3Q7Z3Jv X3RjcC5oJnF1b3Q7PGJyPg0KwqAjaW5jbHVkZSAmcXVvdDtncm9fdnhsYW5fdGNwNC5oJnF1b3Q7 PGJyPg0KPGJyPg0KwqB2b2lkICo8YnI+DQpAQCAtMjQ4LDcgKzI0OSw3IEBAIG1lcmdlX3R3b192 eGxhbl90Y3A0X3BhY2tldHMoc3RydWN0IGdyb192eGxhbl90Y3A0X2l0ZW0gKml0ZW0sPGJyPg0K wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdWludDE2X3Qgb3V0ZXJfaXBfaWQsPGJyPg0KwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgdWludDE2X3QgaXBfaWQpPGJyPg0KwqB7PGJyPg0KLcKgIMKgIMKg IMKgaWYgKG1lcmdlX3R3b190Y3A0X3BhY2tldHMoJmFtcDtpdGVtLSZndDtpbm5lcl9pdGVtLCBw a3QsIGNtcCwgc2VudF9zZXEsPGJyPg0KK8KgIMKgIMKgIMKgaWYgKG1lcmdlX3R3b190Y3BfcGFj a2V0cygmYW1wO2l0ZW0tJmd0O2lubmVyX2l0ZW0sIHBrdCwgY21wLCBzZW50X3NlcSw8YnI+DQrC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpcF9pZCwgcGt0 LSZndDtvdXRlcl9sMl9sZW4gKzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIHBrdC0mZ3Q7b3V0ZXJfbDNfbGVuKSkgezxicj4NCsKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIC8qIFVwZGF0ZSB0aGUgb3V0ZXIgSVB2NCBJRCB0byB0aGUgbGFyZ2UgdmFs dWUuICovPGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vZ3JvX3Z4bGFuX3RjcDQuaCBiL2xpYi9n cm8vZ3JvX3Z4bGFuX3RjcDQuaDxicj4NCmluZGV4IDc4MzI5NDJhNjguLmQ2OGQ1ZmNkNWIgMTAw NjQ0PGJyPg0KLS0tIGEvbGliL2dyby9ncm9fdnhsYW5fdGNwNC5oPGJyPg0KKysrIGIvbGliL2dy by9ncm9fdnhsYW5fdGNwNC5oPGJyPg0KQEAgLTUsNiArNSw3IEBAPGJyPg0KwqAjaWZuZGVmIF9H Uk9fVlhMQU5fVENQNF9IXzxicj4NCsKgI2RlZmluZSBfR1JPX1ZYTEFOX1RDUDRfSF88YnI+DQo8 YnI+DQorI2luY2x1ZGUgJnF1b3Q7Z3JvX3RjcC5oJnF1b3Q7PGJyPg0KwqAjaW5jbHVkZSAmcXVv dDtncm9fdGNwNC5oJnF1b3Q7PGJyPg0KPGJyPg0KwqAjZGVmaW5lIEdST19WWExBTl9UQ1A0X1RC TF9NQVhfSVRFTV9OVU0gKDEwMjRVTCAqIDEwMjRVTCk8YnI+DQpAQCAtMzYsNyArMzcsNyBAQCBz dHJ1Y3QgZ3JvX3Z4bGFuX3RjcDRfZmxvdyB7PGJyPg0KwqB9Ozxicj4NCjxicj4NCsKgc3RydWN0 IGdyb192eGxhbl90Y3A0X2l0ZW0gezxicj4NCi3CoCDCoCDCoCDCoHN0cnVjdCBncm9fdGNwNF9p dGVtIGlubmVyX2l0ZW07PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IGdyb190Y3BfaXRlbSBpbm5l cl9pdGVtOzxicj4NCsKgIMKgIMKgIMKgIC8qIElQdjQgSUQgaW4gdGhlIG91dGVyIElQdjQgaGVh ZGVyICovPGJyPg0KwqAgwqAgwqAgwqAgdWludDE2X3Qgb3V0ZXJfaXBfaWQ7PGJyPg0KwqAgwqAg wqAgwqAgLyogSW5kaWNhdGUgaWYgb3V0ZXIgSVB2NCBJRCBjYW4gYmUgaWdub3JlZCAqLzxicj4N CmRpZmYgLS1naXQgYS9saWIvZ3JvL21lc29uLmJ1aWxkIGIvbGliL2dyby9tZXNvbi5idWlsZDxi cj4NCmluZGV4IGU0ZmEyOTU4YmQuLmRiY2UwNTIyMGQgMTAwNjQ0PGJyPg0KLS0tIGEvbGliL2dy by9tZXNvbi5idWlsZDxicj4NCisrKyBiL2xpYi9ncm8vbWVzb24uYnVpbGQ8YnI+DQpAQCAtNCw2 ICs0LDcgQEA8YnI+DQrCoHNvdXJjZXMgPSBmaWxlcyg8YnI+DQrCoCDCoCDCoCDCoCDCoCYjMzk7 cnRlX2dyby5jJiMzOTssPGJyPg0KwqAgwqAgwqAgwqAgwqAmIzM5O2dyb190Y3A0LmMmIzM5Oyw8 YnI+DQorwqAgwqAgwqAgwqAgJiMzOTtncm9fdGNwNi5jJiMzOTssPGJyPg0KwqAgwqAgwqAgwqAg wqAmIzM5O2dyb191ZHA0LmMmIzM5Oyw8YnI+DQrCoCDCoCDCoCDCoCDCoCYjMzk7Z3JvX3Z4bGFu X3RjcDQuYyYjMzk7LDxicj4NCsKgIMKgIMKgIMKgIMKgJiMzOTtncm9fdnhsYW5fdWRwNC5jJiMz OTssPGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vcnRlX2dyby5jIGIvbGliL2dyby9ydGVfZ3Jv LmM8YnI+DQppbmRleCBlMzUzOTlmZDQyLi5jODE4MGQyNGUzIDEwMDY0NDxicj4NCi0tLSBhL2xp Yi9ncm8vcnRlX2dyby5jPGJyPg0KKysrIGIvbGliL2dyby9ydGVfZ3JvLmM8YnI+DQpAQCAtOCw2 ICs4LDcgQEA8YnI+DQo8YnI+DQrCoCNpbmNsdWRlICZxdW90O3J0ZV9ncm8uaCZxdW90Ozxicj4N CsKgI2luY2x1ZGUgJnF1b3Q7Z3JvX3RjcDQuaCZxdW90Ozxicj4NCisjaW5jbHVkZSAmcXVvdDtn cm9fdGNwNi5oJnF1b3Q7PGJyPg0KwqAjaW5jbHVkZSAmcXVvdDtncm9fdWRwNC5oJnF1b3Q7PGJy Pg0KwqAjaW5jbHVkZSAmcXVvdDtncm9fdnhsYW5fdGNwNC5oJnF1b3Q7PGJyPg0KwqAjaW5jbHVk ZSAmcXVvdDtncm9fdnhsYW5fdWRwNC5oJnF1b3Q7PGJyPg0KQEAgLTIwLDE0ICsyMSwxNiBAQCB0 eXBlZGVmIHVpbnQzMl90ICgqZ3JvX3RibF9wa3RfY291bnRfZm4pKHZvaWQgKnRibCk7PGJyPg0K PGJyPg0KwqBzdGF0aWMgZ3JvX3RibF9jcmVhdGVfZm4gdGJsX2NyZWF0ZV9mbltSVEVfR1JPX1RZ UEVfTUFYX05VTV0gPSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZ3JvX3RjcDRfdGJs X2NyZWF0ZSwgZ3JvX3Z4bGFuX3RjcDRfdGJsX2NyZWF0ZSw8YnI+DQotwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBncm9fdWRwNF90YmxfY3JlYXRlLCBncm9fdnhsYW5fdWRwNF90YmxfY3JlYXRlLCBO VUxMfTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBncm9fdWRwNF90YmxfY3JlYXRlLCBn cm9fdnhsYW5fdWRwNF90YmxfY3JlYXRlLCBncm9fdGNwNl90YmxfY3JlYXRlLCBOVUxMfTs8YnI+ DQrCoHN0YXRpYyBncm9fdGJsX2Rlc3Ryb3lfZm4gdGJsX2Rlc3Ryb3lfZm5bUlRFX0dST19UWVBF X01BWF9OVU1dID0gezxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGdy b190Y3A0X3RibF9kZXN0cm95LCBncm9fdnhsYW5fdGNwNF90YmxfZGVzdHJveSw8YnI+DQrCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBncm9fdWRwNF90YmxfZGVzdHJveSwgZ3Jv X3Z4bGFuX3VkcDRfdGJsX2Rlc3Ryb3ksPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgZ3JvX3RjcDZfdGJsX2Rlc3Ryb3ksPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgTlVMTH07PGJyPg0KwqBzdGF0aWMgZ3JvX3RibF9wa3RfY291bnRfZm4g dGJsX3BrdF9jb3VudF9mbltSVEVfR1JPX1RZUEVfTUFYX05VTV0gPSB7PGJyPg0KwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZ3JvX3RjcDRfdGJsX3BrdF9jb3VudCwgZ3JvX3Z4 bGFuX3RjcDRfdGJsX3BrdF9jb3VudCw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCBncm9fdWRwNF90YmxfcGt0X2NvdW50LCBncm9fdnhsYW5fdWRwNF90YmxfcGt0X2Nv dW50LDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGdyb190Y3A2X3Ri bF9wa3RfY291bnQsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgTlVM TH07PGJyPg0KPGJyPg0KwqAjZGVmaW5lIElTX0lQVjRfVENQX1BLVChwdHlwZSkgKFJURV9FVEhf SVNfSVBWNF9IRFIocHR5cGUpICZhbXA7JmFtcDsgXDxicj4NCkBAIC0zNSw2ICszOCwxMiBAQCBz dGF0aWMgZ3JvX3RibF9wa3RfY291bnRfZm4gdGJsX3BrdF9jb3VudF9mbltSVEVfR1JPX1RZUEVf TUFYX05VTV0gPSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKChwdHlwZSAmYW1wOyBS VEVfUFRZUEVfTDRfRlJBRykgIT0gUlRFX1BUWVBFX0w0X0ZSQUcpICZhbXA7JmFtcDsgXDxicj4N CsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIChSVEVfRVRIX0lTX1RVTk5FTF9QS1QocHR5cGUpID09 IDApKTxicj4NCjxicj4NCisvKiBHUk8gd2l0aCBleHRlbnNpb24gaGVhZGVycyBpcyBub3Qgc3Vw cG9ydGVkICovPGJyPg0KKyNkZWZpbmUgSVNfSVBWNl9UQ1BfUEtUKHB0eXBlKSAoUlRFX0VUSF9J U19JUFY2X0hEUihwdHlwZSkgJmFtcDsmYW1wOyBcPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgKChwdHlwZSAmYW1wOyBSVEVfUFRZUEVfTDRfVENQKSA9PSBSVEVfUFRZUEVfTDRfVENQKSAm YW1wOyZhbXA7IFw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAoKHB0eXBlICZhbXA7IFJU RV9QVFlQRV9MNF9GUkFHKSAhPSBSVEVfUFRZUEVfTDRfRlJBRykgJmFtcDsmYW1wOyBcPGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgKFJURV9FVEhfSVNfVFVOTkVMX1BLVChwdHlwZSkgPT0g MCkpPGJyPg0KKzxicj4NCsKgI2RlZmluZSBJU19JUFY0X1VEUF9QS1QocHR5cGUpIChSVEVfRVRI X0lTX0lQVjRfSERSKHB0eXBlKSAmYW1wOyZhbXA7IFw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCAoKHB0eXBlICZhbXA7IFJURV9QVFlQRV9MNF9VRFApID09IFJURV9QVFlQRV9MNF9VRFAp ICZhbXA7JmFtcDsgXDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIChSVEVfRVRIX0lTX1RV Tk5FTF9QS1QocHR5cGUpID09IDApKTxicj4NCkBAIC0xNDcsNyArMTU2LDExIEBAIHJ0ZV9ncm9f cmVhc3NlbWJsZV9idXJzdChzdHJ1Y3QgcnRlX21idWYgKipwa3RzLDxicj4NCsKgIMKgIMKgIMKg IC8qIGFsbG9jYXRlIGEgcmVhc3NlbWJseSB0YWJsZSBmb3IgVENQL0lQdjQgR1JPICovPGJyPg0K wqAgwqAgwqAgwqAgc3RydWN0IGdyb190Y3A0X3RibCB0Y3BfdGJsOzxicj4NCsKgIMKgIMKgIMKg IHN0cnVjdCBncm9fdGNwNF9mbG93IHRjcF9mbG93c1tSVEVfR1JPX01BWF9CVVJTVF9JVEVNX05V TV07PGJyPg0KLcKgIMKgIMKgIMKgc3RydWN0IGdyb190Y3A0X2l0ZW0gdGNwX2l0ZW1zW1JURV9H Uk9fTUFYX0JVUlNUX0lURU1fTlVNXSA9IHt7MH0gfTs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3Qg Z3JvX3RjcF9pdGVtIHRjcF9pdGVtc1tSVEVfR1JPX01BWF9CVVJTVF9JVEVNX05VTV0gPSB7ezB9 IH07PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBncm9fdGNwNl90YmwgdGNwNl90Ymw7 PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IGdyb190Y3A2X2Zsb3cgdGNwNl9mbG93c1tSVEVfR1JP X01BWF9CVVJTVF9JVEVNX05VTV07PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IGdyb190Y3BfaXRl bSB0Y3A2X2l0ZW1zW1JURV9HUk9fTUFYX0JVUlNUX0lURU1fTlVNXSA9IHt7MH0gfTs8YnI+DQo8 YnI+DQrCoCDCoCDCoCDCoCAvKiBhbGxvY2F0ZSBhIHJlYXNzZW1ibHkgdGFibGUgZm9yIFVEUC9J UHY0IEdSTyAqLzxicj4NCsKgIMKgIMKgIMKgIHN0cnVjdCBncm9fdWRwNF90YmwgdWRwX3RibDs8 YnI+DQpAQCAtMTcxLDEwICsxODQsMTAgQEAgcnRlX2dyb19yZWFzc2VtYmxlX2J1cnN0KHN0cnVj dCBydGVfbWJ1ZiAqKnBrdHMsPGJyPg0KwqAgwqAgwqAgwqAgaW50MzJfdCByZXQ7PGJyPg0KwqAg wqAgwqAgwqAgdWludDE2X3QgaSwgdW5wcm9jZXNzX251bSA9IDAsIG5iX2FmdGVyX2dybyA9IG5i X3BrdHM7PGJyPg0KwqAgwqAgwqAgwqAgdWludDhfdCBkb190Y3A0X2dybyA9IDAsIGRvX3Z4bGFu X3RjcF9ncm8gPSAwLCBkb191ZHA0X2dybyA9IDAsPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgZG9fdnhsYW5fdWRwX2dybyA9IDA7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZG9f dnhsYW5fdWRwX2dybyA9IDAsIGRvX3RjcDZfZ3JvID0gMDs8YnI+DQo8YnI+DQrCoCDCoCDCoCDC oCBpZiAodW5saWtlbHkoKHBhcmFtLSZndDtncm9fdHlwZXMgJmFtcDsgKFJURV9HUk9fSVBWNF9W WExBTl9UQ1BfSVBWNCB8PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgUlRFX0dST19UQ1BfSVBWNCB8PGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgUlRFX0dS T19UQ1BfSVBWNCB8IFJURV9HUk9fVENQX0lQVjYgfDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIFJURV9HUk9fSVBWNF9WWExB Tl9VRFBfSVBWNCB8PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgUlRFX0dST19VRFBfSVBWNCkpID09IDApKTxicj4NCsKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIHJldHVybiBuYl9wa3RzOzxicj4NCkBAIC0yMzYsNiArMjQ5LDE4 IEBAIHJ0ZV9ncm9fcmVhc3NlbWJsZV9idXJzdChzdHJ1Y3QgcnRlX21idWYgKipwa3RzLDxicj4N CsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGRvX3VkcDRfZ3JvID0gMTs8YnI+DQrCoCDCoCDCoCDC oCB9PGJyPg0KPGJyPg0KK8KgIMKgIMKgIMKgaWYgKHBhcmFtLSZndDtncm9fdHlwZXMgJmFtcDsg UlRFX0dST19UQ1BfSVBWNikgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGZvciAoaSA9 IDA7IGkgJmx0OyBpdGVtX251bTsgaSsrKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoHRjcDZfZmxvd3NbaV0uc3RhcnRfaW5kZXggPSBJTlZBTElEX0FSUkFZX0lOREVY Ozxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0Y3A2X3RibC5mbG93cyA9IHRj cDZfZmxvd3M7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGNwNl90YmwuaXRlbXMgPSB0 Y3A2X2l0ZW1zOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRjcDZfdGJsLmZsb3dfbnVt ID0gMDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0Y3A2X3RibC5pdGVtX251bSA9IDA7 PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGNwNl90YmwubWF4X2Zsb3dfbnVtID0gaXRl bV9udW07PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGNwNl90YmwubWF4X2l0ZW1fbnVt ID0gaXRlbV9udW07PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZG9fdGNwNl9ncm8gPSAx Ozxicj4NCivCoCDCoCDCoCDCoH08YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCBmb3IgKGkgPSAwOyBp ICZsdDsgbmJfcGt0czsgaSsrKSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgLyo8YnI+ DQpAQCAtMjc2LDYgKzMwMSwxNCBAQCBydGVfZ3JvX3JlYXNzZW1ibGVfYnVyc3Qoc3RydWN0IHJ0 ZV9tYnVmICoqcGt0cyw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCBuYl9hZnRlcl9ncm8tLTs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCBlbHNlIGlmIChyZXQgJmx0OyAwKTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHVucHJvY2Vzc19wa3RzW3VucHJvY2Vzc19udW0r K10gPSBwa3RzW2ldOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH0gZWxzZSBpZiAoSVNf SVBWNl9UQ1BfUEtUKHBrdHNbaV0tJmd0O3BhY2tldF90eXBlKSAmYW1wOyZhbXA7IDxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGRvX3RjcDZfZ3Jv KSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0ID0gZ3JvX3Rj cDZfcmVhc3NlbWJsZShwa3RzW2ldLCAmYW1wO3RjcDZfdGJsLCAwKTs8YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAocmV0ICZndDsgMCk8YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiBtZXJnZSBzdWNjZXNzZnVs bHkgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBuYl9hZnRlcl9ncm8tLTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBlbHNlIGlmIChyZXQgJmx0OyAwKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHVucHJvY2Vzc19wa3RzW3VucHJvY2Vzc19udW0rK10gPSBwa3Rz W2ldOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIH0gZWxzZTxicj4NCsKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHVucHJvY2Vzc19wa3RzW3VucHJvY2Vzc19udW0rK10g PSBwa3RzW2ldOzxicj4NCsKgIMKgIMKgIMKgIH08YnI+DQpAQCAtMjgzLDkgKzMxNiwxNyBAQCBy dGVfZ3JvX3JlYXNzZW1ibGVfYnVyc3Qoc3RydWN0IHJ0ZV9tYnVmICoqcGt0cyw8YnI+DQrCoCDC oCDCoCDCoCBpZiAoKG5iX2FmdGVyX2dybyAmbHQ7IG5iX3BrdHMpPGJyPg0KwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqB8fCAodW5wcm9jZXNzX251bSAmbHQ7IG5iX3BrdHMpKSB7PGJyPg0KwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgaSA9IDA7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg LyogQ29weSB1bnByb2Nlc3NlZCBwYWNrZXRzICovPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgaWYgKHVucHJvY2Vzc19udW0gJmd0OyAwKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgbWVtY3B5KCZhbXA7cGt0c1tpXSwgdW5wcm9jZXNzX3BrdHMsPGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgc2l6ZW9mKHN0cnVjdCBydGVfbWJ1ZiAqKSAqPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdW5wcm9jZXNzX251bSk7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaSA9IHVucHJvY2Vzc19udW07 PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfTxicj4NCis8YnI+DQrCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCAvKiBGbHVzaCBhbGwgcGFja2V0cyBmcm9tIHRoZSB0YWJsZXMgKi88YnI+DQrC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoZG9fdnhsYW5fdGNwX2dybykgezxicj4NCi3CoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGkgPSBncm9fdnhsYW5fdGNwNF90YmxfdGlt ZW91dF9mbHVzaCgmYW1wO3Z4bGFuX3RjcF90YmwsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgaSArPSBncm9fdnhsYW5fdGNwNF90YmxfdGltZW91dF9mbHVzaCgmYW1w O3Z4bGFuX3RjcF90YmwsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgMCwgcGt0cywgbmJfcGt0cyk7PGJyPg0KwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgfTxicj4NCjxicj4NCkBAIC0zMDQsMTMgKzM0NSwxMSBAQCBydGVfZ3Jv X3JlYXNzZW1ibGVfYnVyc3Qoc3RydWN0IHJ0ZV9tYnVmICoqcGt0cyw8YnI+DQrCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpICs9IGdyb191ZHA0X3RibF90aW1lb3V0X2ZsdXNo KCZhbXA7dWRwX3RibCwgMCw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmYW1wO3BrdHNbaV0sIG5iX3BrdHMgLSBpKTs8YnI+ DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg LyogQ29weSB1bnByb2Nlc3NlZCBwYWNrZXRzICovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgaWYgKHVucHJvY2Vzc19udW0gJmd0OyAwKSB7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgbWVtY3B5KCZhbXA7cGt0c1tpXSwgdW5wcm9jZXNzX3BrdHMsPGJyPg0K LcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgc2l6ZW9mKHN0cnVjdCBydGVfbWJ1ZiAqKSAqPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdW5wcm9jZXNzX251bSk7PGJy Pg0KKzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChkb190Y3A2X2dybykgezxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGkgKz0gZ3JvX3RjcDZfdGJsX3Rp bWVvdXRfZmx1c2goJmFtcDt0Y3A2X3RibCwgMCwgPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgJmFtcDtwa3RzW2ldLCBuYl9w a3RzIC0gaSk7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfTxicj4NCi3CoCDCoCDCoCDC oCDCoCDCoCDCoCDCoG5iX2FmdGVyX2dybyA9IGkgKyB1bnByb2Nlc3NfbnVtOzxicj4NCsKgIMKg IMKgIMKgIH08YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCByZXR1cm4gbmJfYWZ0ZXJfZ3JvOzxicj4N CkBAIC0zMjMsMTMgKzM2MiwxMyBAQCBydGVfZ3JvX3JlYXNzZW1ibGUoc3RydWN0IHJ0ZV9tYnVm ICoqcGt0cyw8YnI+DQrCoHs8YnI+DQrCoCDCoCDCoCDCoCBzdHJ1Y3QgcnRlX21idWYgKnVucHJv Y2Vzc19wa3RzW25iX3BrdHNdOzxicj4NCsKgIMKgIMKgIMKgIHN0cnVjdCBncm9fY3R4ICpncm9f Y3R4ID0gY3R4Ozxicj4NCi3CoCDCoCDCoCDCoHZvaWQgKnRjcF90YmwsICp1ZHBfdGJsLCAqdnhs YW5fdGNwX3RibCwgKnZ4bGFuX3VkcF90Ymw7PGJyPg0KK8KgIMKgIMKgIMKgdm9pZCAqdGNwX3Ri bCwgKnVkcF90YmwsICp2eGxhbl90Y3BfdGJsLCAqdnhsYW5fdWRwX3RibCwgKnRjcDZfdGJsOzxi cj4NCsKgIMKgIMKgIMKgIHVpbnQ2NF90IGN1cnJlbnRfdGltZTs8YnI+DQrCoCDCoCDCoCDCoCB1 aW50MTZfdCBpLCB1bnByb2Nlc3NfbnVtID0gMDs8YnI+DQotwqAgwqAgwqAgwqB1aW50OF90IGRv X3RjcDRfZ3JvLCBkb192eGxhbl90Y3BfZ3JvLCBkb191ZHA0X2dybywgZG9fdnhsYW5fdWRwX2dy bzs8YnI+DQorwqAgwqAgwqAgwqB1aW50OF90IGRvX3RjcDRfZ3JvLCBkb192eGxhbl90Y3BfZ3Jv LCBkb191ZHA0X2dybywgZG9fdnhsYW5fdWRwX2dybywgZG9fdGNwNl9ncm87PGJyPg0KPGJyPg0K wqAgwqAgwqAgwqAgaWYgKHVubGlrZWx5KChncm9fY3R4LSZndDtncm9fdHlwZXMgJmFtcDsgKFJU RV9HUk9fSVBWNF9WWExBTl9UQ1BfSVBWNCB8PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgUlRFX0dST19UQ1BfSVBWNCB8PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgUlRFX0dST19UQ1BfSVBWNCB8IFJURV9HUk9fVENQX0lQVjYgfCA8YnI+DQrCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBSVEVf R1JPX0lQVjRfVlhMQU5fVURQX0lQVjQgfDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIFJURV9HUk9fVURQX0lQVjQpKSA9PSAw KSk8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXR1cm4gbmJfcGt0czs8YnI+DQpAQCAt MzM4LDYgKzM3Nyw3IEBAIHJ0ZV9ncm9fcmVhc3NlbWJsZShzdHJ1Y3QgcnRlX21idWYgKipwa3Rz LDxicj4NCsKgIMKgIMKgIMKgIHZ4bGFuX3RjcF90YmwgPSBncm9fY3R4LSZndDt0YmxzW1JURV9H Uk9fSVBWNF9WWExBTl9UQ1BfSVBWNF9JTkRFWF07PGJyPg0KwqAgwqAgwqAgwqAgdWRwX3RibCA9 IGdyb19jdHgtJmd0O3RibHNbUlRFX0dST19VRFBfSVBWNF9JTkRFWF07PGJyPg0KwqAgwqAgwqAg wqAgdnhsYW5fdWRwX3RibCA9IGdyb19jdHgtJmd0O3RibHNbUlRFX0dST19JUFY0X1ZYTEFOX1VE UF9JUFY0X0lOREVYXTs8YnI+DQorwqAgwqAgwqAgwqB0Y3A2X3RibCA9IGdyb19jdHgtJmd0O3Ri bHNbUlRFX0dST19UQ1BfSVBWNl9JTkRFWF07PGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgZG9fdGNw NF9ncm8gPSAoZ3JvX2N0eC0mZ3Q7Z3JvX3R5cGVzICZhbXA7IFJURV9HUk9fVENQX0lQVjQpID09 PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgUlRFX0dST19UQ1BfSVBWNDs8YnI+DQpAQCAt MzQ3LDYgKzM4Nyw3IEBAIHJ0ZV9ncm9fcmVhc3NlbWJsZShzdHJ1Y3QgcnRlX21idWYgKipwa3Rz LDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIFJURV9HUk9fVURQX0lQVjQ7PGJyPg0KwqAg wqAgwqAgwqAgZG9fdnhsYW5fdWRwX2dybyA9IChncm9fY3R4LSZndDtncm9fdHlwZXMgJmFtcDsg UlRFX0dST19JUFY0X1ZYTEFOX1VEUF9JUFY0KSA9PTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIFJURV9HUk9fSVBWNF9WWExBTl9VRFBfSVBWNDs8YnI+DQorwqAgwqAgwqAgwqBkb190Y3A2 X2dybyA9IChncm9fY3R4LSZndDtncm9fdHlwZXMgJmFtcDsgUlRFX0dST19UQ1BfSVBWNikgPT0g UlRFX0dST19UQ1BfSVBWNjs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCBjdXJyZW50X3RpbWUgPSBy dGVfcmR0c2MoKTs8YnI+DQo8YnI+DQpAQCAtMzcxLDcgKzQxMiwxMyBAQCBydGVfZ3JvX3JlYXNz ZW1ibGUoc3RydWN0IHJ0ZV9tYnVmICoqcGt0cyw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCBpZiAoZ3JvX3VkcDRfcmVhc3NlbWJsZShwa3RzW2ldLCB1ZHBfdGJsLDxi cj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIGN1cnJlbnRfdGltZSkgJmx0OyAwKTxicj4NCsKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHVucHJvY2Vzc19wa3RzW3VucHJv Y2Vzc19udW0rK10gPSBwa3RzW2ldOzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH0gZWxz ZTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH0gZWxzZSBpZiAoSVNfSVBWNl9UQ1BfUEtU KHBrdHNbaV0tJmd0O3BhY2tldF90eXBlKSAmYW1wOyZhbXA7IDxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGRvX3RjcDZfZ3JvKSB7PGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGdyb190Y3A2X3JlYXNzZW1ibGUo cGt0c1tpXSwgdGNwNl90YmwsIDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGN1cnJlbnRfdGltZSkgJmx0 OyAwKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oHVucHJvY2Vzc19wa3RzW3VucHJvY2Vzc19udW0rK10gPSBwa3RzW2ldOzxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBlbHNlPGJyPg0K wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdW5wcm9jZXNzX3BrdHNbdW5wcm9j ZXNzX251bSsrXSA9IHBrdHNbaV07PGJyPg0KwqAgwqAgwqAgwqAgfTxicj4NCsKgIMKgIMKgIMKg IGlmICh1bnByb2Nlc3NfbnVtICZndDsgMCkgezxicj4NCkBAIC00MjYsNiArNDczLDE1IEBAIHJ0 ZV9ncm9fdGltZW91dF9mbHVzaCh2b2lkICpjdHgsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZ3JvX2N0eC0mZ3Q7dGJsc1tSVEVfR1JPX1VEUF9J UFY0X0lOREVYXSw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCBmbHVzaF90aW1lc3RhbXAsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgJmFtcDtvdXRbbnVtXSwgbGVmdF9uYl9vdXQpOzxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoGxlZnRfbmJfb3V0ID0gbWF4X25iX291dCAtIG51bTs8YnI+ DQorwqAgwqAgwqAgwqB9PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGlmICgoZ3JvX3R5cGVzICZh bXA7IFJURV9HUk9fVENQX0lQVjYpICZhbXA7JmFtcDsgbGVmdF9uYl9vdXQgJmd0OyAwKSB7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbnVtICs9IGdyb190Y3A2X3RibF90aW1lb3V0X2Zs dXNoKDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oGdyb19jdHgtJmd0O3RibHNbUlRFX0dST19UQ1BfSVBWNl9JTkRFWF0sPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZmx1c2hfdGltZXN0YW1wLDxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCZhbXA7 b3V0W251bV0sIGxlZnRfbmJfb3V0KTs8YnI+DQorPGJyPg0KwqAgwqAgwqAgwqAgfTxicj4NCjxi cj4NCsKgIMKgIMKgIMKgIHJldHVybiBudW07PGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vcnRl X2dyby5oIGIvbGliL2dyby9ydGVfZ3JvLmg8YnI+DQppbmRleCA5ZjllZDQ5MzVhLi5hYzVhNDY0 Y2YxIDEwMDY0NDxicj4NCi0tLSBhL2xpYi9ncm8vcnRlX2dyby5oPGJyPg0KKysrIGIvbGliL2dy by9ydGVfZ3JvLmg8YnI+DQpAQCAtMzcsNiArMzcsOSBAQCBleHRlcm4gJnF1b3Q7QyZxdW90OyB7 PGJyPg0KwqAvKiombHQ7IFVEUC9JUHY0IEdSTyBmbGFnICovPGJyPg0KwqAjZGVmaW5lIFJURV9H Uk9fSVBWNF9WWExBTl9VRFBfSVBWNF9JTkRFWCAzPGJyPg0KwqAjZGVmaW5lIFJURV9HUk9fSVBW NF9WWExBTl9VRFBfSVBWNCAoMVVMTCAmbHQ7Jmx0OyBSVEVfR1JPX0lQVjRfVlhMQU5fVURQX0lQ VjRfSU5ERVgpPGJyPg0KKzxicj4NCisjZGVmaW5lIFJURV9HUk9fVENQX0lQVjZfSU5ERVggNDxi cj4NCisjZGVmaW5lIFJURV9HUk9fVENQX0lQVjYgKDFVTEwgJmx0OyZsdDsgUlRFX0dST19UQ1Bf SVBWNl9JTkRFWCk8YnI+DQrCoC8qKiZsdDsgVnhMQU4gVURQL0lQdjQgR1JPIGZsYWcuICovPGJy Pg0KPGJyPg0KwqAvKio8YnI+DQotLSA8YnI+DQoyLjI1LjE8YnI+DQo8YnI+DQo8L2Jsb2NrcXVv dGU+PC9kaXY+PC9kaXY+PC9kaXY+DQo= --000000000000a218b805f80c9e63--