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 83AE142C98; Mon, 12 Jun 2023 14:04:22 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 526C340689; Mon, 12 Jun 2023 14:04:22 +0200 (CEST) Received: from mail-yw1-f171.google.com (mail-yw1-f171.google.com [209.85.128.171]) by mails.dpdk.org (Postfix) with ESMTP id EEE9B4014F for ; Mon, 12 Jun 2023 14:04:19 +0200 (CEST) Received: by mail-yw1-f171.google.com with SMTP id 00721157ae682-56ce6bbe274so23938527b3.1 for ; Mon, 12 Jun 2023 05:04:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1686571459; x=1689163459; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=SbKK6ZKQrszP3SMqeVh596y/BFyPPY6VPACAbo5fYw0=; b=FpllBEiL78p+BkEDTJwj9UFBxOEjTlHAA4yscqmm1IhH3pnDlf7pKdzi/y1I4qPJBN hgf4aeVwSzNZVbNBWGveAr9q+EPHOK213hbmUf5BF7Oxtuq2jZeMOUVT/WwcFTGOwwX4 UH7+4ah6/tfBwEyknwW4unqR9EqmOaIRW3Kc4qNFraNRPz9BHQCpEjBpxMqoTfI8G2pc P5wwUNuqcUxKmNqb0/8K8xnS2/H0FGem3+ekY3ywF8wzAahZJ/N54AydwtRa4mGmGByz FeRzM8Rk5r2lNPLLpBabFNdjkP6rQBiS9oyDK6hGGPrIIfDlVM9YJK0jbSwlHji7qnEM 43EQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686571459; x=1689163459; 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=SbKK6ZKQrszP3SMqeVh596y/BFyPPY6VPACAbo5fYw0=; b=kzTSXc5kdzeXdmLVfw5IGmlo3arNAVr5cBe/v+mLHmw75od7FkueRjP+tcD1AiJagV XED2X/aT63G+HEXjGLXPAdMOzFcUbrwF7vsjveDdHg3vNVWu9dwxtvPyIQG527vBX9er thUPEj+O40q/FheOY/zQqw3FuBeJsOjXx3ZwfQ9rq8yfl1iCxx30SseaAee8QGay3PUo Itk7OBVYmv63SFsWnUAqYiOcz/8GJ8YU53LSZgt6LIT0Qnh8cNztL4+k9hWA5xVBikEV 5SorcAR9vRbksuq9Nivurqx9V9KjowcX9k+xiqdUfAMM3gepk2gB7VCgqdZe+TdGSWs6 XPHA== X-Gm-Message-State: AC+VfDwOjP9d+T2W9SVXsL9A8GDjuMGCnoeoZRXoC+N7zAI+iuvs1HwL frN6d637FghuCv1r1xEt+9pQ7CPvoZ2cueTc8er4Y6tIaSQ= X-Google-Smtp-Source: ACHHUZ4+iLYXH3CUnEUcN5l7wJGrbRcEHdkEYWpCAanoNgjvJSvnZwgF/B253Pd/ODExNIodwoYURCw7E1Q5Df/D7Bk= X-Received: by 2002:a0d:eb83:0:b0:56d:7c4:8be8 with SMTP id u125-20020a0deb83000000b0056d07c48be8mr5460827ywe.16.1686571458887; Mon, 12 Jun 2023 05:04:18 -0700 (PDT) MIME-Version: 1.0 References: <20221020181425.48006-1-kumaraparmesh92@gmail.com> <20230612113110.72345-1-kumaraparamesh92@gmail.com> In-Reply-To: <20230612113110.72345-1-kumaraparamesh92@gmail.com> From: kumaraparameshwaran rathinavel Date: Mon, 12 Jun 2023 17:34:07 +0530 Message-ID: Subject: Re: [PATCH v7] gro : ipv6 changes to support GRO for TCP/ipv6 To: jiayu.hu@intel.com Cc: dev@dpdk.org Content-Type: multipart/alternative; boundary="000000000000b205c405fded8460" 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 --000000000000b205c405fded8460 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Mon, Jun 12, 2023 at 5:01=E2=80=AFPM Kumara Parameshwaran < kumaraparamesh92@gmail.com> wrote: > The patch adds GRO support for TCP/ipv6 packets. This does not > include the support for vxlan, udp ipv6 packets. > > Signed-off-by: Kumara Parameshwaran > --- > v1: > * Changes to support GRO for TCP/ipv6 packets. This does not > include > vxlan changes. > * The GRO is performed only for ipv6 packets that does not contai= n > extension headers. > * The logic for the TCP coalescing remains the same, in ipv6 > header > the source address, destination address, flow label, version > fields > are expected to be the same. > * Re-organised the code to reuse certain tcp functions for both > ipv4 and > ipv6 flows. > v2: > * Fix comments in gro_tcp6.h header file. > > v3: > * Adderess review comments to fix code duplication for v4 and v6 > > v4: > * Addresses review comments for v3, do not use callbacks > > v5: > * Address review comments > > v6: > * Fix warning and coding style issues > > v7: > * Fix build compilation issue > lib/gro/gro_tcp4.c | 178 ++++++------------------- > lib/gro/gro_tcp4.h | 170 +---------------------- > lib/gro/gro_tcp6.c | 267 +++++++++++++++++++++++++++++++++++++ > lib/gro/gro_tcp6.h | 161 ++++++++++++++++++++++ > lib/gro/gro_tcp_internal.c | 128 ++++++++++++++++++ > lib/gro/gro_tcp_internal.h | 212 +++++++++++++++++++++++++++++ > lib/gro/gro_vxlan_tcp4.c | 23 ++-- > lib/gro/gro_vxlan_tcp4.h | 3 +- > lib/gro/meson.build | 2 + > lib/gro/rte_gro.c | 83 ++++++++++-- > lib/gro/rte_gro.h | 3 + > 11 files changed, 897 insertions(+), 333 deletions(-) > create mode 100644 lib/gro/gro_tcp6.c > create mode 100644 lib/gro/gro_tcp6.h > create mode 100644 lib/gro/gro_tcp_internal.c > create mode 100644 lib/gro/gro_tcp_internal.h > > diff --git a/lib/gro/gro_tcp4.c b/lib/gro/gro_tcp4.c > index 0014096e63..42fee78f30 100644 > --- a/lib/gro/gro_tcp4.c > +++ b/lib/gro/gro_tcp4.c > @@ -30,7 +30,7 @@ gro_tcp4_tbl_create(uint16_t socket_id, > if (tbl =3D=3D NULL) > return NULL; > > - size =3D sizeof(struct gro_tcp4_item) * entries_num; > + size =3D sizeof(struct gro_tcp_item) * entries_num; > tbl->items =3D rte_zmalloc_socket(__func__, > size, > RTE_CACHE_LINE_SIZE, > @@ -71,18 +71,6 @@ gro_tcp4_tbl_destroy(void *tbl) > rte_free(tcp_tbl); > } > > -static inline uint32_t > -find_an_empty_item(struct gro_tcp4_tbl *tbl) > -{ > - uint32_t i; > - uint32_t max_item_num =3D tbl->max_item_num; > - > - for (i =3D 0; i < max_item_num; i++) > - if (tbl->items[i].firstseg =3D=3D NULL) > - return i; > - return INVALID_ARRAY_INDEX; > -} > - > static inline uint32_t > find_an_empty_flow(struct gro_tcp4_tbl *tbl) > { > @@ -95,56 +83,6 @@ find_an_empty_flow(struct gro_tcp4_tbl *tbl) > return INVALID_ARRAY_INDEX; > } > > -static inline uint32_t > -insert_new_item(struct gro_tcp4_tbl *tbl, > - struct rte_mbuf *pkt, > - uint64_t start_time, > - uint32_t prev_idx, > - uint32_t sent_seq, > - uint16_t ip_id, > - uint8_t is_atomic) > -{ > - uint32_t item_idx; > - > - item_idx =3D find_an_empty_item(tbl); > - if (item_idx =3D=3D INVALID_ARRAY_INDEX) > - return INVALID_ARRAY_INDEX; > - > - tbl->items[item_idx].firstseg =3D pkt; > - tbl->items[item_idx].lastseg =3D rte_pktmbuf_lastseg(pkt); > - tbl->items[item_idx].start_time =3D start_time; > - tbl->items[item_idx].next_pkt_idx =3D INVALID_ARRAY_INDEX; > - tbl->items[item_idx].sent_seq =3D sent_seq; > - tbl->items[item_idx].ip_id =3D ip_id; > - tbl->items[item_idx].nb_merged =3D 1; > - tbl->items[item_idx].is_atomic =3D is_atomic; > - tbl->item_num++; > - > - /* if the previous packet exists, chain them together. */ > - if (prev_idx !=3D INVALID_ARRAY_INDEX) { > - tbl->items[item_idx].next_pkt_idx =3D > - tbl->items[prev_idx].next_pkt_idx; > - tbl->items[prev_idx].next_pkt_idx =3D item_idx; > - } > - > - return item_idx; > -} > - > -static inline uint32_t > -delete_item(struct gro_tcp4_tbl *tbl, uint32_t item_idx, > - uint32_t prev_item_idx) > -{ > - uint32_t next_idx =3D tbl->items[item_idx].next_pkt_idx; > - > - /* NULL indicates an empty item */ > - tbl->items[item_idx].firstseg =3D NULL; > - tbl->item_num--; > - if (prev_item_idx !=3D INVALID_ARRAY_INDEX) > - tbl->items[prev_item_idx].next_pkt_idx =3D next_idx; > - > - return next_idx; > -} > - > static inline uint32_t > insert_new_flow(struct gro_tcp4_tbl *tbl, > struct tcp4_flow_key *src, > @@ -159,13 +97,10 @@ insert_new_flow(struct gro_tcp4_tbl *tbl, > > dst =3D &(tbl->flows[flow_idx].key); > > - rte_ether_addr_copy(&(src->eth_saddr), &(dst->eth_saddr)); > - rte_ether_addr_copy(&(src->eth_daddr), &(dst->eth_daddr)); > + ASSIGN_COMMON_TCP_KEY((&src->cmn_key), (&dst->cmn_key)); > + > dst->ip_src_addr =3D src->ip_src_addr; > dst->ip_dst_addr =3D src->ip_dst_addr; > - dst->recv_ack =3D src->recv_ack; > - dst->src_port =3D src->src_port; > - dst->dst_port =3D src->dst_port; > > tbl->flows[flow_idx].start_index =3D item_idx; > tbl->flow_num++; > @@ -173,21 +108,6 @@ insert_new_flow(struct gro_tcp4_tbl *tbl, > return flow_idx; > } > > -/* > - * update the packet length for the flushed packet. > - */ > -static inline void > -update_header(struct gro_tcp4_item *item) > -{ > - struct rte_ipv4_hdr *ipv4_hdr; > - struct rte_mbuf *pkt =3D item->firstseg; > - > - ipv4_hdr =3D (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(pkt, char *= ) + > - pkt->l2_len); > - ipv4_hdr->total_length =3D rte_cpu_to_be_16(pkt->pkt_len - > - pkt->l2_len); > -} > - > int32_t > gro_tcp4_reassemble(struct rte_mbuf *pkt, > struct gro_tcp4_tbl *tbl, > @@ -202,9 +122,8 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > uint8_t is_atomic; > > struct tcp4_flow_key key; > - uint32_t cur_idx, prev_idx, item_idx; > + uint32_t item_idx; > uint32_t i, max_flow_num, remaining_flow_num; > - int cmp; > uint8_t find; > > /* > @@ -216,7 +135,7 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > > eth_hdr =3D rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); > ipv4_hdr =3D (struct rte_ipv4_hdr *)((char *)eth_hdr + pkt->l2_le= n); > - tcp_hdr =3D (struct rte_tcp_hdr *)((char *)ipv4_hdr + pkt->l3_len= ); > + tcp_hdr =3D rte_pktmbuf_mtod_offset(pkt, struct rte_tcp_hdr *, > pkt->l2_len + pkt->l3_len); > hdr_len =3D pkt->l2_len + pkt->l3_len + pkt->l4_len; > > /* > @@ -230,7 +149,6 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > ip_tlen =3D rte_be_to_cpu_16(ipv4_hdr->total_length); > if (pkt->pkt_len > (uint32_t)(ip_tlen + pkt->l2_len)) > rte_pktmbuf_trim(pkt, pkt->pkt_len - ip_tlen - > pkt->l2_len); > - > /* > * Don't process the packet whose payload length is less than or > * equal to 0. > @@ -239,6 +157,13 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > if (tcp_dl <=3D 0) > return -1; > > + rte_ether_addr_copy(&(eth_hdr->src_addr), > &(key.cmn_key.eth_saddr)); > + rte_ether_addr_copy(&(eth_hdr->dst_addr), > &(key.cmn_key.eth_daddr)); > + key.ip_src_addr =3D ipv4_hdr->src_addr; > + key.ip_dst_addr =3D ipv4_hdr->dst_addr; > + key.cmn_key.src_port =3D tcp_hdr->src_port; > + key.cmn_key.dst_port =3D tcp_hdr->dst_port; > + key.cmn_key.recv_ack =3D tcp_hdr->recv_ack; > /* > * Save IPv4 ID for the packet whose DF bit is 0. For the packet > * whose DF bit is 1, IPv4 ID is ignored. > @@ -246,15 +171,6 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > frag_off =3D rte_be_to_cpu_16(ipv4_hdr->fragment_offset); > is_atomic =3D (frag_off & RTE_IPV4_HDR_DF_FLAG) =3D=3D > RTE_IPV4_HDR_DF_FLAG; > ip_id =3D is_atomic ? 0 : rte_be_to_cpu_16(ipv4_hdr->packet_id); > - sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > - > - rte_ether_addr_copy(&(eth_hdr->src_addr), &(key.eth_saddr)); > - rte_ether_addr_copy(&(eth_hdr->dst_addr), &(key.eth_daddr)); > - key.ip_src_addr =3D ipv4_hdr->src_addr; > - key.ip_dst_addr =3D ipv4_hdr->dst_addr; > - key.src_port =3D tcp_hdr->src_port; > - key.dst_port =3D tcp_hdr->dst_port; > - key.recv_ack =3D tcp_hdr->recv_ack; > > /* Search for a matched flow. */ > max_flow_num =3D tbl->max_flow_num; > @@ -270,63 +186,44 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt, > } > } > > - /* > - * Fail to find a matched flow. Insert a new flow and store the > - * packet into the flow. > - */ > if (find =3D=3D 0) { > - item_idx =3D insert_new_item(tbl, pkt, start_time, > - INVALID_ARRAY_INDEX, sent_seq, ip_id, > - is_atomic); > + sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > + item_idx =3D insert_new_tcp_item(pkt, tbl->items, > &tbl->item_num, > + tbl->max_item_num, > start_time, > + INVALID_ARRAY_INDEX, > sent_seq, ip_id, > + is_atomic); > if (item_idx =3D=3D INVALID_ARRAY_INDEX) > return -1; > if (insert_new_flow(tbl, &key, item_idx) =3D=3D > - INVALID_ARRAY_INDEX) { > + INVALID_ARRAY_INDEX) { > /* > * Fail to insert a new flow, so delete the > * stored packet. > - */ > - delete_item(tbl, item_idx, INVALID_ARRAY_INDEX); > + */ > + delete_tcp_item(tbl->items, item_idx, > &tbl->item_num, INVALID_ARRAY_INDEX); > return -1; > } > return 0; > } > > - /* > - * Check all packets in the flow and try to find a neighbor for > - * the input packet. > - */ > - cur_idx =3D tbl->flows[i].start_index; > - prev_idx =3D cur_idx; > - do { > - cmp =3D check_seq_option(&(tbl->items[cur_idx]), tcp_hdr, > - sent_seq, ip_id, pkt->l4_len, tcp_dl, 0, > - is_atomic); > - if (cmp) { > - if (merge_two_tcp4_packets(&(tbl->items[cur_idx])= , > - pkt, cmp, sent_seq, ip_id= , > 0)) > - return 1; > - /* > - * Fail to merge the two packets, as the packet > - * length is greater than the max value. Store > - * the packet into the flow. > - */ > - if (insert_new_item(tbl, pkt, start_time, cur_idx= , > - sent_seq, ip_id, > is_atomic) =3D=3D > - INVALID_ARRAY_INDEX) > - return -1; > - return 0; > - } > - prev_idx =3D cur_idx; > - cur_idx =3D tbl->items[cur_idx].next_pkt_idx; > - } while (cur_idx !=3D INVALID_ARRAY_INDEX); > + return process_tcp_item(pkt, tcp_hdr, tcp_dl, tbl->items, > tbl->flows[i].start_index, > + &tbl->item_num, > tbl->max_item_num, > + ip_id, is_atomic, > start_time); > +} > > - /* Fail to find a neighbor, so store the packet into the flow. */ > - if (insert_new_item(tbl, pkt, start_time, prev_idx, sent_seq, > - ip_id, is_atomic) =3D=3D INVALID_ARRAY_IN= DEX) > - return -1; > +/* > + * update the packet length for the flushed packet. > + */ > +static inline void > +update_header(struct gro_tcp_item *item) > +{ > + struct rte_ipv4_hdr *ipv4_hdr; > + struct rte_mbuf *pkt =3D item->firstseg; > > - return 0; > + ipv4_hdr =3D (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(pkt, char *= ) + > + pkt->l2_len); > + ipv4_hdr->total_length =3D rte_cpu_to_be_16(pkt->pkt_len - > + pkt->l2_len); > } > > uint16_t > @@ -353,7 +250,8 @@ gro_tcp4_tbl_timeout_flush(struct gro_tcp4_tbl *tbl, > * Delete the packet and get the next > * packet in the flow. > */ > - j =3D delete_item(tbl, j, > INVALID_ARRAY_INDEX); > + j =3D delete_tcp_item(tbl->items, j, > + &tbl->item_num, > INVALID_ARRAY_INDEX); > tbl->flows[i].start_index =3D j; > if (j =3D=3D INVALID_ARRAY_INDEX) > tbl->flow_num--; > diff --git a/lib/gro/gro_tcp4.h b/lib/gro/gro_tcp4.h > index 212f97a042..c0154afa24 100644 > --- a/lib/gro/gro_tcp4.h > +++ b/lib/gro/gro_tcp4.h > @@ -5,32 +5,15 @@ > #ifndef _GRO_TCP4_H_ > #define _GRO_TCP4_H_ > > -#include > +#include > > -#define INVALID_ARRAY_INDEX 0xffffffffUL > #define GRO_TCP4_TBL_MAX_ITEM_NUM (1024UL * 1024UL) > > -/* > - * The max length of a IPv4 packet, which includes the length of the L3 > - * header, the L4 header and the data payload. > - */ > -#define MAX_IPV4_PKT_LENGTH UINT16_MAX > - > -/* The maximum TCP header length */ > -#define MAX_TCP_HLEN 60 > -#define INVALID_TCP_HDRLEN(len) \ > - (((len) < sizeof(struct rte_tcp_hdr)) || ((len) > MAX_TCP_HLEN)) > - > -/* Header fields representing a TCP/IPv4 flow */ > +/* Header fields representing common fields in TCP flow */ > struct tcp4_flow_key { > - struct rte_ether_addr eth_saddr; > - struct rte_ether_addr eth_daddr; > + struct cmn_tcp_key cmn_key; > uint32_t ip_src_addr; > uint32_t ip_dst_addr; > - > - uint32_t recv_ack; > - uint16_t src_port; > - uint16_t dst_port; > }; > > struct gro_tcp4_flow { > @@ -42,42 +25,12 @@ struct gro_tcp4_flow { > uint32_t start_index; > }; > > -struct gro_tcp4_item { > - /* > - * The first MBUF segment of the packet. If the value > - * is NULL, it means the item is empty. > - */ > - struct rte_mbuf *firstseg; > - /* The last MBUF segment of the packet */ > - struct rte_mbuf *lastseg; > - /* > - * The time when the first packet is inserted into the table. > - * This value won't be updated, even if the packet is merged > - * with other packets. > - */ > - uint64_t start_time; > - /* > - * next_pkt_idx is used to chain the packets that > - * are in the same flow but can't be merged together > - * (e.g. caused by packet reordering). > - */ > - uint32_t next_pkt_idx; > - /* TCP sequence number of the packet */ > - uint32_t sent_seq; > - /* IPv4 ID of the packet */ > - uint16_t ip_id; > - /* the number of merged packets */ > - uint16_t nb_merged; > - /* Indicate if IPv4 ID can be ignored */ > - uint8_t is_atomic; > -}; > - > /* > * TCP/IPv4 reassembly table structure. > */ > struct gro_tcp4_tbl { > /* item array */ > - struct gro_tcp4_item *items; > + struct gro_tcp_item *items; > /* flow array */ > struct gro_tcp4_flow *flows; > /* current item number */ > @@ -186,120 +139,9 @@ uint32_t gro_tcp4_tbl_pkt_count(void *tbl); > static inline int > is_same_tcp4_flow(struct tcp4_flow_key k1, struct tcp4_flow_key k2) > { > - return (rte_is_same_ether_addr(&k1.eth_saddr, &k2.eth_saddr) && > - rte_is_same_ether_addr(&k1.eth_daddr, > &k2.eth_daddr) && > - (k1.ip_src_addr =3D=3D k2.ip_src_addr) && > + return ((k1.ip_src_addr =3D=3D k2.ip_src_addr) && > (k1.ip_dst_addr =3D=3D k2.ip_dst_addr) && > - (k1.recv_ack =3D=3D k2.recv_ack) && > - (k1.src_port =3D=3D k2.src_port) && > - (k1.dst_port =3D=3D k2.dst_port)); > + is_common_tcp_key(&k1.cmn_key, &k2.cmn_key)); > } > > -/* > - * Merge two TCP/IPv4 packets without updating checksums. > - * If cmp is larger than 0, append the new packet to the > - * original packet. Otherwise, pre-pend the new packet to > - * the original packet. > - */ > -static inline int > -merge_two_tcp4_packets(struct gro_tcp4_item *item, > - struct rte_mbuf *pkt, > - int cmp, > - uint32_t sent_seq, > - uint16_t ip_id, > - uint16_t l2_offset) > -{ > - struct rte_mbuf *pkt_head, *pkt_tail, *lastseg; > - uint16_t hdr_len, l2_len; > - > - if (cmp > 0) { > - pkt_head =3D item->firstseg; > - pkt_tail =3D pkt; > - } else { > - pkt_head =3D pkt; > - pkt_tail =3D item->firstseg; > - } > - > - /* check if the IPv4 packet length is greater than the max value = */ > - hdr_len =3D l2_offset + pkt_head->l2_len + pkt_head->l3_len + > - pkt_head->l4_len; > - l2_len =3D l2_offset > 0 ? pkt_head->outer_l2_len : pkt_head->l2_= len; > - if (unlikely(pkt_head->pkt_len - l2_len + pkt_tail->pkt_len - > - hdr_len > MAX_IPV4_PKT_LENGTH)) > - return 0; > - > - /* remove the packet header for the tail packet */ > - rte_pktmbuf_adj(pkt_tail, hdr_len); > - > - /* chain two packets together */ > - if (cmp > 0) { > - item->lastseg->next =3D pkt; > - item->lastseg =3D rte_pktmbuf_lastseg(pkt); > - /* update IP ID to the larger value */ > - item->ip_id =3D ip_id; > - } else { > - lastseg =3D rte_pktmbuf_lastseg(pkt); > - lastseg->next =3D item->firstseg; > - item->firstseg =3D pkt; > - /* update sent_seq to the smaller value */ > - item->sent_seq =3D sent_seq; > - item->ip_id =3D ip_id; > - } > - item->nb_merged++; > - > - /* update MBUF metadata for the merged packet */ > - pkt_head->nb_segs +=3D pkt_tail->nb_segs; > - pkt_head->pkt_len +=3D pkt_tail->pkt_len; > - > - return 1; > -} > - > -/* > - * Check if two TCP/IPv4 packets are neighbors. > - */ > -static inline int > -check_seq_option(struct gro_tcp4_item *item, > - struct rte_tcp_hdr *tcph, > - uint32_t sent_seq, > - uint16_t ip_id, > - uint16_t tcp_hl, > - uint16_t tcp_dl, > - uint16_t l2_offset, > - uint8_t is_atomic) > -{ > - struct rte_mbuf *pkt_orig =3D item->firstseg; > - struct rte_ipv4_hdr *iph_orig; > - struct rte_tcp_hdr *tcph_orig; > - uint16_t len, tcp_hl_orig; > - > - iph_orig =3D (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(pkt_orig, c= har > *) + > - l2_offset + pkt_orig->l2_len); > - tcph_orig =3D (struct rte_tcp_hdr *)((char *)iph_orig + > pkt_orig->l3_len); > - tcp_hl_orig =3D pkt_orig->l4_len; > - > - /* Check if TCP option fields equal */ > - len =3D RTE_MAX(tcp_hl, tcp_hl_orig) - sizeof(struct rte_tcp_hdr)= ; > - if ((tcp_hl !=3D tcp_hl_orig) || ((len > 0) && > - (memcmp(tcph + 1, tcph_orig + 1, > - len) !=3D 0))) > - return 0; > - > - /* Don't merge packets whose DF bits are different */ > - if (unlikely(item->is_atomic ^ is_atomic)) > - return 0; > - > - /* check if the two packets are neighbors */ > - len =3D pkt_orig->pkt_len - l2_offset - pkt_orig->l2_len - > - pkt_orig->l3_len - tcp_hl_orig; > - if ((sent_seq =3D=3D item->sent_seq + len) && (is_atomic || > - (ip_id =3D=3D item->ip_id + 1))) > - /* append the new packet */ > - return 1; > - else if ((sent_seq + tcp_dl =3D=3D item->sent_seq) && (is_atomic = || > - (ip_id + item->nb_merged =3D=3D item->ip_= id))) > - /* pre-pend the new packet */ > - return -1; > - > - return 0; > -} > #endif > diff --git a/lib/gro/gro_tcp6.c b/lib/gro/gro_tcp6.c > new file mode 100644 > index 0000000000..0ea73741c1 > --- /dev/null > +++ b/lib/gro/gro_tcp6.c > @@ -0,0 +1,267 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2017 Intel Corporation > + */ > + > +#include > +#include > +#include > + > +#include "gro_tcp6.h" > + > +void * > +gro_tcp6_tbl_create(uint16_t socket_id, > + uint16_t max_flow_num, > + uint16_t max_item_per_flow) > +{ > + struct gro_tcp6_tbl *tbl; > + size_t size; > + uint32_t entries_num, i; > + > + entries_num =3D max_flow_num * max_item_per_flow; > + entries_num =3D RTE_MIN(entries_num, GRO_TCP6_TBL_MAX_ITEM_NUM); > + > + if (entries_num =3D=3D 0) > + return NULL; > + > + tbl =3D rte_zmalloc_socket(__func__, > + sizeof(struct gro_tcp6_tbl), > + RTE_CACHE_LINE_SIZE, > + socket_id); > + if (tbl =3D=3D NULL) > + return NULL; > + > + size =3D sizeof(struct gro_tcp_item) * entries_num; > + tbl->items =3D rte_zmalloc_socket(__func__, > + size, > + RTE_CACHE_LINE_SIZE, > + socket_id); > + if (tbl->items =3D=3D NULL) { > + rte_free(tbl); > + return NULL; > + } > + tbl->max_item_num =3D entries_num; > + > + size =3D sizeof(struct gro_tcp6_flow) * entries_num; > + tbl->flows =3D rte_zmalloc_socket(__func__, > + size, > + RTE_CACHE_LINE_SIZE, > + socket_id); > + if (tbl->flows =3D=3D NULL) { > + rte_free(tbl->items); > + rte_free(tbl); > + return NULL; > + } > + /* INVALID_ARRAY_INDEX indicates an empty flow */ > + for (i =3D 0; i < entries_num; i++) > + tbl->flows[i].start_index =3D INVALID_ARRAY_INDEX; > + tbl->max_flow_num =3D entries_num; > + > + return tbl; > +} > + > +void > +gro_tcp6_tbl_destroy(void *tbl) > +{ > + struct gro_tcp6_tbl *tcp_tbl =3D tbl; > + > + if (tcp_tbl) { > + rte_free(tcp_tbl->items); > + rte_free(tcp_tbl->flows); > + } > + rte_free(tcp_tbl); > +} > + > +static inline uint32_t > +find_an_empty_flow(struct gro_tcp6_tbl *tbl) > +{ > + uint32_t i; > + uint32_t max_flow_num =3D tbl->max_flow_num; > + > + for (i =3D 0; i < max_flow_num; i++) > + if (tbl->flows[i].start_index =3D=3D INVALID_ARRAY_INDEX) > + return i; > + return INVALID_ARRAY_INDEX; > +} > + > +static inline uint32_t > +insert_new_flow(struct gro_tcp6_tbl *tbl, > + struct tcp6_flow_key *src, > + uint32_t item_idx) > +{ > + struct tcp6_flow_key *dst; > + uint32_t flow_idx; > + > + flow_idx =3D find_an_empty_flow(tbl); > + if (unlikely(flow_idx =3D=3D INVALID_ARRAY_INDEX)) > + return INVALID_ARRAY_INDEX; > + > + dst =3D &(tbl->flows[flow_idx].key); > + > + ASSIGN_COMMON_TCP_KEY((&src->cmn_key), (&dst->cmn_key)); > + memcpy(&dst->src_addr[0], &src->src_addr[0], > sizeof(dst->src_addr)); > + memcpy(&dst->dst_addr[0], &src->dst_addr[0], > sizeof(dst->dst_addr)); > + dst->vtc_flow =3D src->vtc_flow; > + > + tbl->flows[flow_idx].start_index =3D item_idx; > + tbl->flow_num++; > + > + return flow_idx; > +} > + > +/* > + * update the packet length for the flushed packet. > + */ > +static inline void > +update_header(struct gro_tcp_item *item) > +{ > + struct rte_ipv6_hdr *ipv6_hdr; > + struct rte_mbuf *pkt =3D item->firstseg; > + > + ipv6_hdr =3D (struct rte_ipv6_hdr *)(rte_pktmbuf_mtod(pkt, char *= ) + > + pkt->l2_len); > + ipv6_hdr->payload_len =3D rte_cpu_to_be_16(pkt->pkt_len - > + pkt->l2_len - pkt->l3_len); > +} > + > +int32_t > +gro_tcp6_reassemble(struct rte_mbuf *pkt, > + struct gro_tcp6_tbl *tbl, > + uint64_t start_time) > +{ > + struct rte_ether_hdr *eth_hdr; > + struct rte_ipv6_hdr *ipv6_hdr; > + int32_t tcp_dl; > + uint16_t ip_tlen; > + struct tcp6_flow_key key; > + uint32_t i, max_flow_num, remaining_flow_num; > + uint32_t sent_seq; > + struct rte_tcp_hdr *tcp_hdr; > + uint8_t find; > + uint32_t item_idx; > + /* > + * Don't process the packet whose TCP header length is greater > + * than 60 bytes or less than 20 bytes. > + */ > + if (unlikely(INVALID_TCP_HDRLEN(pkt->l4_len))) > + return -1; > + > + eth_hdr =3D rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); > + ipv6_hdr =3D (struct rte_ipv6_hdr *)((char *)eth_hdr + pkt->l2_le= n); > + tcp_hdr =3D rte_pktmbuf_mtod_offset(pkt, struct rte_tcp_hdr *, > pkt->l2_len + pkt->l3_len); > + > + /* > + * Don't process the packet which has FIN, SYN, RST, PSH, URG, EC= E > + * or CWR set. > + */ > + if (tcp_hdr->tcp_flags !=3D RTE_TCP_ACK_FLAG) > + return -1; > + > + ip_tlen =3D rte_be_to_cpu_16(ipv6_hdr->payload_len); > + /* > + * Don't process the packet whose payload length is less than or > + * equal to 0. > + */ > + tcp_dl =3D ip_tlen - pkt->l4_len; > + if (tcp_dl <=3D 0) > + return -1; > + > + rte_ether_addr_copy(&(eth_hdr->src_addr), > &(key.cmn_key.eth_saddr)); > + rte_ether_addr_copy(&(eth_hdr->dst_addr), > &(key.cmn_key.eth_daddr)); > + memcpy(&key.src_addr[0], &ipv6_hdr->src_addr, > sizeof(key.src_addr)); > + memcpy(&key.dst_addr[0], &ipv6_hdr->dst_addr, > sizeof(key.dst_addr)); > + key.cmn_key.src_port =3D tcp_hdr->src_port; > + key.cmn_key.dst_port =3D tcp_hdr->dst_port; > + key.cmn_key.recv_ack =3D tcp_hdr->recv_ack; > + key.vtc_flow =3D ipv6_hdr->vtc_flow; > + > + /* Search for a matched flow. */ > + max_flow_num =3D tbl->max_flow_num; > + remaining_flow_num =3D tbl->flow_num; > + find =3D 0; > + for (i =3D 0; i < max_flow_num && remaining_flow_num; i++) { > + if (tbl->flows[i].start_index !=3D INVALID_ARRAY_INDEX) { > + if (is_same_tcp6_flow(&tbl->flows[i].key, &key)) = { > + find =3D 1; > + break; > + } > + remaining_flow_num--; > + } > + } > + > + if (find =3D=3D 0) { > + sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > + item_idx =3D insert_new_tcp_item(pkt, tbl->items, > &tbl->item_num, > + tbl->max_item_num, > start_time, > + INVALID_ARRAY_INDEX, > sent_seq, 0, true); > + if (item_idx =3D=3D INVALID_ARRAY_INDEX) > + return -1; > + if (insert_new_flow(tbl, &key, item_idx) =3D=3D > + INVALID_ARRAY_INDEX) { > + /* > + * Fail to insert a new flow, so delete the > + * stored packet. > + */ > + delete_tcp_item(tbl->items, item_idx, > &tbl->item_num, INVALID_ARRAY_INDEX); > + return -1; > + } > + return 0; > + } > + > + return process_tcp_item(pkt, tcp_hdr, tcp_dl, tbl->items, > tbl->flows[i].start_index, > + &tbl->item_num, > tbl->max_item_num, > + 0, true, start_time); > +} > + > +uint16_t > +gro_tcp6_tbl_timeout_flush(struct gro_tcp6_tbl *tbl, > + uint64_t flush_timestamp, > + struct rte_mbuf **out, > + uint16_t nb_out) > +{ > + uint16_t k =3D 0; > + uint32_t i, j; > + uint32_t max_flow_num =3D tbl->max_flow_num; > + > + for (i =3D 0; i < max_flow_num; i++) { > + if (unlikely(tbl->flow_num =3D=3D 0)) > + return k; > + > + j =3D tbl->flows[i].start_index; > + while (j !=3D INVALID_ARRAY_INDEX) { > + if (tbl->items[j].start_time <=3D flush_timestamp= ) { > + out[k++] =3D tbl->items[j].firstseg; > + if (tbl->items[j].nb_merged > 1) > + update_header(&(tbl->items[j])); > + /* > + * Delete the packet and get the next > + * packet in the flow. > + */ > + j =3D delete_tcp_item(tbl->items, j, > + &tbl->item_num, > INVALID_ARRAY_INDEX); > + tbl->flows[i].start_index =3D j; > + if (j =3D=3D INVALID_ARRAY_INDEX) > + tbl->flow_num--; > + > + if (unlikely(k =3D=3D nb_out)) > + return k; > + } else > + /* > + * The left packets in this flow won't be > + * timeout. Go to check other flows. > + */ > + break; > + } > + } > + return k; > +} > + > +uint32_t > +gro_tcp6_tbl_pkt_count(void *tbl) > +{ > + struct gro_tcp6_tbl *gro_tbl =3D tbl; > + > + if (gro_tbl) > + return gro_tbl->item_num; > + > + return 0; > +} > diff --git a/lib/gro/gro_tcp6.h b/lib/gro/gro_tcp6.h > new file mode 100644 > index 0000000000..cc02b0004a > --- /dev/null > +++ b/lib/gro/gro_tcp6.h > @@ -0,0 +1,161 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2017 Intel Corporation > + */ > + > +#ifndef _GRO_TCP6_H_ > +#define _GRO_TCP6_H_ > + > +#include > + > +#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 cmn_tcp_key cmn_key; > + uint8_t src_addr[16]; > + uint8_t dst_addr[16]; > + rte_be32_t vtc_flow; > +}; > + > +struct gro_tcp6_flow { > + struct tcp6_flow_key key; > + /* > + * The index of the first packet in the flow. > + * INVALID_ARRAY_INDEX indicates an empty flow. > + */ > + uint32_t start_index; > +}; > + > +/* > + * TCP/IPv6 reassembly table structure. > + */ > +struct gro_tcp6_tbl { > + /* item array */ > + struct gro_tcp_item *items; > + /* flow array */ > + struct gro_tcp6_flow *flows; > + /* current item number */ > + uint32_t item_num; > + /* current flow num */ > + uint32_t flow_num; > + /* item array size */ > + uint32_t max_item_num; > + /* flow array size */ > + uint32_t max_flow_num; > +}; > + > +/** > + * This function creates a TCP/IPv6 reassembly table. > + * > + * @param socket_id > + * Socket index for allocating the TCP/IPv6 reassemble table > + * @param max_flow_num > + * The maximum number of flows in the TCP/IPv6 GRO table > + * @param max_item_per_flow > + * The maximum number of packets per flow > + * > + * @return > + * - Return the table pointer on success. > + * - Return NULL on failure. > + */ > +void *gro_tcp6_tbl_create(uint16_t socket_id, > + uint16_t max_flow_num, > + uint16_t max_item_per_flow); > + > +/** > + * This function destroys a TCP/IPv6 reassembly table. > + * > + * @param tbl > + * Pointer pointing to the TCP/IPv6 reassembly table. > + */ > +void gro_tcp6_tbl_destroy(void *tbl); > + > +/** > + * This function merges a TCP/IPv6 packet. It doesn't process the packet= , > + * which has SYN, FIN, RST, PSH, CWR, ECE or URG set, or doesn't have > + * payload. > + * > + * This function doesn't check if the packet has correct checksums and > + * doesn't re-calculate checksums for the merged packet. Additionally, > + * it assumes the packets are complete (i.e., MF=3D=3D0 && frag_off=3D= =3D0), > + * when IP fragmentation is possible (i.e., DF=3D=3D0). It returns the > + * packet, if the packet has invalid parameters (e.g. SYN bit is set) > + * or there is no available space in the table. > + * > + * @param pkt > + * Packet to reassemble > + * @param tbl > + * Pointer pointing to the TCP/IPv6 reassembly table > + * @start_time > + * The time when the packet is inserted into the table > + * > + * @return > + * - Return a positive value if the packet is merged. > + * - Return zero if the packet isn't merged but stored in the table. > + * - Return a negative value for invalid parameters or no available > + * space in the table. > + */ > +int32_t gro_tcp6_reassemble(struct rte_mbuf *pkt, > + struct gro_tcp6_tbl *tbl, > + uint64_t start_time); > + > +/** > + * This function flushes timeout packets in a TCP/IPv6 reassembly table, > + * and without updating checksums. > + * > + * @param tbl > + * TCP/IPv6 reassembly table pointer > + * @param flush_timestamp > + * Flush packets which are inserted into the table before or at the > + * flush_timestamp. > + * @param out > + * Pointer array used to keep flushed packets > + * @param nb_out > + * The element number in 'out'. It also determines the maximum number o= f > + * packets that can be flushed finally. > + * > + * @return > + * The number of flushed packets > + */ > +uint16_t gro_tcp6_tbl_timeout_flush(struct gro_tcp6_tbl *tbl, > + uint64_t flush_timestamp, > + struct rte_mbuf **out, > + uint16_t nb_out); > + > +/** > + * This function returns the number of the packets in a TCP/IPv6 > + * reassembly table. > + * > + * @param tbl > + * TCP/IPv6 reassembly table pointer > + * > + * @return > + * The number of packets in the table > + */ > +uint32_t gro_tcp6_tbl_pkt_count(void *tbl); > + > +/* > + * Check if two TCP/IPv6 packets belong to the same flow. > + */ > +static inline int > +is_same_tcp6_flow(struct tcp6_flow_key *k1, struct tcp6_flow_key *k2) > +{ > + rte_be32_t vtc_flow_diff; > + > + if (memcmp(&k1->src_addr, &k2->src_addr, 16)) > + return 0; > + if (memcmp(&k1->dst_addr, &k2->dst_addr, 16)) > + return 0; > + /* > + * IP version (4) Traffic Class (8) Flow Label (20) > + * All fields except Traffic class should be same > + */ > + vtc_flow_diff =3D (k1->vtc_flow ^ k2->vtc_flow); > + if (vtc_flow_diff & htonl(0xF00FFFFF)) > + return 0; > + > + return is_common_tcp_key(&k1->cmn_key, &k2->cmn_key); > +} > + > +#endif > diff --git a/lib/gro/gro_tcp_internal.c b/lib/gro/gro_tcp_internal.c > new file mode 100644 > index 0000000000..5a21bca7f8 > --- /dev/null > +++ b/lib/gro/gro_tcp_internal.c > @@ -0,0 +1,128 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2017 Intel Corporation > + */ > +#include > +#include > +#include > + > +#include "gro_tcp_internal.h" > + > +static inline uint32_t > +find_an_empty_item(struct gro_tcp_item *items, > + uint32_t max_item_num) > +{ > + uint32_t i; > + > + for (i =3D 0; i < max_item_num; i++) > + if (items[i].firstseg =3D=3D NULL) > + return i; > + return INVALID_ARRAY_INDEX; > +} > + > +inline uint32_t > +insert_new_tcp_item(struct rte_mbuf *pkt, > + struct gro_tcp_item *items, > + uint32_t *item_num, > + uint32_t max_item_num, > + uint64_t start_time, > + uint32_t prev_idx, > + uint32_t sent_seq, > + uint16_t ip_id, > + uint8_t is_atomic) > +{ > + uint32_t item_idx; > + > + item_idx =3D find_an_empty_item(items, max_item_num); > + if (item_idx =3D=3D INVALID_ARRAY_INDEX) > + return INVALID_ARRAY_INDEX; > + > + items[item_idx].firstseg =3D pkt; > + items[item_idx].lastseg =3D rte_pktmbuf_lastseg(pkt); > + items[item_idx].start_time =3D start_time; > + items[item_idx].next_pkt_idx =3D INVALID_ARRAY_INDEX; > + items[item_idx].sent_seq =3D sent_seq; > + items[item_idx].l3.ip_id =3D ip_id; > + items[item_idx].nb_merged =3D 1; > + items[item_idx].is_atomic =3D is_atomic; > + (*item_num) +=3D 1; > + > + /* if the previous packet exists, chain them together. */ > + if (prev_idx !=3D INVALID_ARRAY_INDEX) { > + items[item_idx].next_pkt_idx =3D > + items[prev_idx].next_pkt_idx; > + items[prev_idx].next_pkt_idx =3D item_idx; > + } > + > + return item_idx; > +} > + > +inline uint32_t > +delete_tcp_item(struct gro_tcp_item *items, uint32_t item_idx, > + uint32_t *item_num, > + uint32_t prev_item_idx) > +{ > + uint32_t next_idx =3D items[item_idx].next_pkt_idx; > + > + /* NULL indicates an empty item */ > + items[item_idx].firstseg =3D NULL; > + (*item_num) -=3D 1; > + if (prev_item_idx !=3D INVALID_ARRAY_INDEX) > + items[prev_item_idx].next_pkt_idx =3D next_idx; > + > + return next_idx; > +} > + > +int32_t > +process_tcp_item(struct rte_mbuf *pkt, > + struct rte_tcp_hdr *tcp_hdr, > + int32_t tcp_dl, > + struct gro_tcp_item *items, > + uint32_t item_idx, > + uint32_t *item_num, > + uint32_t max_item_num, > + uint16_t ip_id, > + uint8_t is_atomic, > + uint64_t start_time) > +{ > + uint32_t cur_idx; > + uint32_t prev_idx; > + int cmp; > + uint32_t sent_seq; > + > + sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > + /* > + * Check all packets in the flow and try to find a neighbor for > + * the input packet. > + */ > + cur_idx =3D item_idx; > + prev_idx =3D cur_idx; > + do { > + cmp =3D check_seq_option(&items[cur_idx], tcp_hdr, > + sent_seq, ip_id, pkt->l4_len, tcp_dl, 0, > + is_atomic); > + if (cmp) { > + if (merge_two_tcp_packets(&items[cur_idx], > + pkt, cmp, sent_seq, ip_id= , > 0)) > + return 1; > + /* > + * Fail to merge the two packets, as the packet > + * length is greater than the max value. Store > + * the packet into the flow. > + */ > + if (insert_new_tcp_item(pkt, items, item_num, > max_item_num, > + start_time, cur_idx, > sent_seq, ip_id, is_atomic) =3D=3D > + INVALID_ARRAY_INDEX) > + return -1; > + return 0; > + } > + prev_idx =3D cur_idx; > + cur_idx =3D items[cur_idx].next_pkt_idx; > + } while (cur_idx !=3D INVALID_ARRAY_INDEX); > + > + /* Fail to find a neighbor, so store the packet into the flow. */ > + if (insert_new_tcp_item(pkt, items, item_num, max_item_num, > start_time, prev_idx, sent_seq, > + ip_id, is_atomic) =3D=3D INVALID_ARRAY_IN= DEX) > + return -1; > + > + return 0; > +} > diff --git a/lib/gro/gro_tcp_internal.h b/lib/gro/gro_tcp_internal.h > new file mode 100644 > index 0000000000..072b7aea13 > --- /dev/null > +++ b/lib/gro/gro_tcp_internal.h > @@ -0,0 +1,212 @@ > +#ifndef _GRO_TCP_H_ > +#define _GRO_TCP_H_ > + > +#define INVALID_ARRAY_INDEX 0xffffffffUL > + > +#include > + > +/* > + * The max length of a IPv4 packet, which includes the length of the L3 > + * header, the L4 header and the data payload. > + */ > +#define MAX_IP_PKT_LENGTH UINT16_MAX > + > +/* The maximum TCP header length */ > +#define MAX_TCP_HLEN 60 > +#define INVALID_TCP_HDRLEN(len) \ > + (((len) < sizeof(struct rte_tcp_hdr)) || ((len) > MAX_TCP_HLEN)) > + > +struct cmn_tcp_key { > + struct rte_ether_addr eth_saddr; > + struct rte_ether_addr eth_daddr; > + uint32_t recv_ack; > + uint16_t src_port; > + uint16_t dst_port; > +}; > + > +#define ASSIGN_COMMON_TCP_KEY(k1, k2) \ > + do {\ > + rte_ether_addr_copy(&(k1->eth_saddr), &(k2->eth_saddr)); = \ > + rte_ether_addr_copy(&(k1->eth_daddr), &(k2->eth_daddr)); = \ > + k2->recv_ack =3D k1->recv_ack; \ > + k2->src_port =3D k1->src_port; \ > + k2->dst_port =3D k1->dst_port; \ > + } while (0) > + > +struct gro_tcp_item { > + /* > + * The first MBUF segment of the packet. If the value > + * is NULL, it means the item is empty. > + */ > + struct rte_mbuf *firstseg; > + /* The last MBUF segment of the packet */ > + struct rte_mbuf *lastseg; > + /* > + * The time when the first packet is inserted into the table. > + * This value won't be updated, even if the packet is merged > + * with other packets. > + */ > + uint64_t start_time; > + /* > + * next_pkt_idx is used to chain the packets that > + * are in the same flow but can't be merged together > + * (e.g. caused by packet reordering). > + */ > + uint32_t next_pkt_idx; > + /* TCP sequence number of the packet */ > + uint32_t sent_seq; > + union { > + /* IPv4 ID of the packet */ > + uint16_t ip_id; > + /* Unused field for IPv6 */ > + uint16_t unused; > + } l3; > + /* the number of merged packets */ > + uint16_t nb_merged; > + /* Indicate if IPv4 ID can be ignored */ > + uint8_t is_atomic; > +}; > + > +uint32_t > +insert_new_tcp_item(struct rte_mbuf *pkt, > + struct gro_tcp_item *items, > + uint32_t *item_num, > + uint32_t max_item_num, > + uint64_t start_time, > + uint32_t prev_idx, > + uint32_t sent_seq, > + uint16_t ip_id, > + uint8_t is_atomic); > + > +uint32_t > +delete_tcp_item(struct gro_tcp_item *items, uint32_t item_idx, > + uint32_t *item_num, > + uint32_t prev_item_idx); > + > +int32_t > +process_tcp_item(struct rte_mbuf *pkt, > + struct rte_tcp_hdr *tcp_hdr, > + int32_t tcp_dl, > + struct gro_tcp_item *items, > + uint32_t item_idx, > + uint32_t *item_num, > + uint32_t max_item_num, > + uint16_t ip_id, > + uint8_t is_atomic, > + uint64_t start_time); > + > +/* > + * Merge two TCP packets without updating checksums. > + * If cmp is larger than 0, append the new packet to the > + * original packet. Otherwise, pre-pend the new packet to > + * the original packet. > + */ > +static inline int > +merge_two_tcp_packets(struct gro_tcp_item *item, > + struct rte_mbuf *pkt, > + int cmp, > + uint32_t sent_seq, > + uint16_t ip_id, > + uint16_t l2_offset) > +{ > + struct rte_mbuf *pkt_head, *pkt_tail, *lastseg; > + uint16_t hdr_len, l2_len; > + > + if (cmp > 0) { > + pkt_head =3D item->firstseg; > + pkt_tail =3D pkt; > + } else { > + pkt_head =3D pkt; > + pkt_tail =3D item->firstseg; > + } > + > + /* check if the IPv4 packet length is greater than the max value = */ > + hdr_len =3D l2_offset + pkt_head->l2_len + pkt_head->l3_len + > + pkt_head->l4_len; > + l2_len =3D l2_offset > 0 ? pkt_head->outer_l2_len : pkt_head->l2_= len; > + if (unlikely(pkt_head->pkt_len - l2_len + pkt_tail->pkt_len - > + hdr_len > MAX_IP_PKT_LENGTH)) > + return 0; > + > + /* remove the packet header for the tail packet */ > + rte_pktmbuf_adj(pkt_tail, hdr_len); > + > + /* chain two packets together */ > + if (cmp > 0) { > + item->lastseg->next =3D pkt; > + item->lastseg =3D rte_pktmbuf_lastseg(pkt); > + /* update IP ID to the larger value */ > + item->l3.ip_id =3D ip_id; > + } else { > + lastseg =3D rte_pktmbuf_lastseg(pkt); > + lastseg->next =3D item->firstseg; > + item->firstseg =3D pkt; > + /* update sent_seq to the smaller value */ > + item->sent_seq =3D sent_seq; > + item->l3.ip_id =3D ip_id; > + } > + item->nb_merged++; > + > + /* update MBUF metadata for the merged packet */ > + pkt_head->nb_segs +=3D pkt_tail->nb_segs; > + pkt_head->pkt_len +=3D pkt_tail->pkt_len; > + > + return 1; > +} > + > +/* > + * Check if two TCP/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->l3.ip_id + 1))) > + /* append the new packet */ > + return 1; > + else if ((sent_seq + tcp_dl =3D=3D item->sent_seq) && (is_atomic = || > + (ip_id + item->nb_merged =3D=3D > item->l3.ip_id))) > + /* pre-pend the new packet */ > + return -1; > + > + return 0; > +} > + > +static inline int > +is_common_tcp_key(struct cmn_tcp_key *k1, struct cmn_tcp_key *k2) > +{ > + return (!memcmp(k1, k2, sizeof(struct cmn_tcp_key))); > +} > + > +#endif > diff --git a/lib/gro/gro_vxlan_tcp4.c b/lib/gro/gro_vxlan_tcp4.c > index 3be4deb7c7..81eebf0d2d 100644 > --- a/lib/gro/gro_vxlan_tcp4.c > +++ b/lib/gro/gro_vxlan_tcp4.c > @@ -7,6 +7,7 @@ > #include > #include > > +#include "gro_tcp_internal.h" > #include "gro_vxlan_tcp4.h" > > void * > @@ -116,7 +117,7 @@ insert_new_item(struct gro_vxlan_tcp4_tbl *tbl, > tbl->items[item_idx].inner_item.start_time =3D start_time; > tbl->items[item_idx].inner_item.next_pkt_idx =3D INVALID_ARRAY_IN= DEX; > tbl->items[item_idx].inner_item.sent_seq =3D sent_seq; > - tbl->items[item_idx].inner_item.ip_id =3D ip_id; > + tbl->items[item_idx].inner_item.l3.ip_id =3D ip_id; > tbl->items[item_idx].inner_item.nb_merged =3D 1; > tbl->items[item_idx].inner_item.is_atomic =3D is_atomic; > tbl->items[item_idx].outer_ip_id =3D outer_ip_id; > @@ -163,15 +164,9 @@ insert_new_flow(struct gro_vxlan_tcp4_tbl *tbl, > > dst =3D &(tbl->flows[flow_idx].key); > > - rte_ether_addr_copy(&(src->inner_key.eth_saddr), > - &(dst->inner_key.eth_saddr)); > - rte_ether_addr_copy(&(src->inner_key.eth_daddr), > - &(dst->inner_key.eth_daddr)); > + ASSIGN_COMMON_TCP_KEY((&(src->inner_key.cmn_key)), > (&(dst->inner_key.cmn_key))); > dst->inner_key.ip_src_addr =3D src->inner_key.ip_src_addr; > dst->inner_key.ip_dst_addr =3D src->inner_key.ip_dst_addr; > - dst->inner_key.recv_ack =3D src->inner_key.recv_ack; > - dst->inner_key.src_port =3D src->inner_key.src_port; > - dst->inner_key.dst_port =3D src->inner_key.dst_port; > > dst->vxlan_hdr.vx_flags =3D src->vxlan_hdr.vx_flags; > dst->vxlan_hdr.vx_vni =3D src->vxlan_hdr.vx_vni; > @@ -248,7 +243,7 @@ merge_two_vxlan_tcp4_packets(struct > gro_vxlan_tcp4_item *item, > uint16_t outer_ip_id, > uint16_t ip_id) > { > - if (merge_two_tcp4_packets(&item->inner_item, pkt, cmp, sent_seq, > + if (merge_two_tcp_packets(&item->inner_item, pkt, cmp, sent_seq, > ip_id, pkt->outer_l2_len + > pkt->outer_l3_len)) { > /* Update the outer IPv4 ID to the large value. */ > @@ -357,13 +352,13 @@ gro_vxlan_tcp4_reassemble(struct rte_mbuf *pkt, > > sent_seq =3D rte_be_to_cpu_32(tcp_hdr->sent_seq); > > - rte_ether_addr_copy(&(eth_hdr->src_addr), > &(key.inner_key.eth_saddr)); > - rte_ether_addr_copy(&(eth_hdr->dst_addr), > &(key.inner_key.eth_daddr)); > + rte_ether_addr_copy(&(eth_hdr->src_addr), > &(key.inner_key.cmn_key.eth_saddr)); > + rte_ether_addr_copy(&(eth_hdr->dst_addr), > &(key.inner_key.cmn_key.eth_daddr)); > key.inner_key.ip_src_addr =3D ipv4_hdr->src_addr; > key.inner_key.ip_dst_addr =3D ipv4_hdr->dst_addr; > - key.inner_key.recv_ack =3D tcp_hdr->recv_ack; > - key.inner_key.src_port =3D tcp_hdr->src_port; > - key.inner_key.dst_port =3D tcp_hdr->dst_port; > + key.inner_key.cmn_key.recv_ack =3D tcp_hdr->recv_ack; > + key.inner_key.cmn_key.src_port =3D tcp_hdr->src_port; > + key.inner_key.cmn_key.dst_port =3D tcp_hdr->dst_port; > > key.vxlan_hdr.vx_flags =3D vxlan_hdr->vx_flags; > key.vxlan_hdr.vx_vni =3D vxlan_hdr->vx_vni; > diff --git a/lib/gro/gro_vxlan_tcp4.h b/lib/gro/gro_vxlan_tcp4.h > index 7832942a68..82eaaee11e 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_internal.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..1640317890 100644 > --- a/lib/gro/meson.build > +++ b/lib/gro/meson.build > @@ -3,7 +3,9 @@ > > sources =3D files( > 'rte_gro.c', > + 'gro_tcp_internal.c', > 'gro_tcp4.c', > + 'gro_tcp6.c', > 'gro_udp4.c', > 'gro_vxlan_tcp4.c', > 'gro_vxlan_udp4.c', > diff --git a/lib/gro/rte_gro.c b/lib/gro/rte_gro.c > index e35399fd42..d824eebd93 100644 > --- a/lib/gro/rte_gro.c > +++ b/lib/gro/rte_gro.c > @@ -8,6 +8,7 @@ > > #include "rte_gro.h" > #include "gro_tcp4.h" > +#include "gro_tcp6.h" > #include "gro_udp4.h" > #include "gro_vxlan_tcp4.h" > #include "gro_vxlan_udp4.h" > @@ -20,14 +21,16 @@ typedef uint32_t (*gro_tbl_pkt_count_fn)(void *tbl); > > static gro_tbl_create_fn tbl_create_fn[RTE_GRO_TYPE_MAX_NUM] =3D { > gro_tcp4_tbl_create, gro_vxlan_tcp4_tbl_create, > - gro_udp4_tbl_create, gro_vxlan_udp4_tbl_create, NULL}; > + gro_udp4_tbl_create, gro_vxlan_udp4_tbl_create, > gro_tcp6_tbl_create, NULL}; > static gro_tbl_destroy_fn tbl_destroy_fn[RTE_GRO_TYPE_MAX_NUM] =3D { > gro_tcp4_tbl_destroy, gro_vxlan_tcp4_tbl_destroy, > gro_udp4_tbl_destroy, gro_vxlan_udp4_tbl_destroy, > + gro_tcp6_tbl_destroy, > NULL}; > static gro_tbl_pkt_count_fn tbl_pkt_count_fn[RTE_GRO_TYPE_MAX_NUM] =3D { > gro_tcp4_tbl_pkt_count, > gro_vxlan_tcp4_tbl_pkt_count, > gro_udp4_tbl_pkt_count, > gro_vxlan_udp4_tbl_pkt_count, > + gro_tcp6_tbl_pkt_count, > NULL}; > > #define IS_IPV4_TCP_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \ > @@ -35,6 +38,12 @@ static gro_tbl_pkt_count_fn > tbl_pkt_count_fn[RTE_GRO_TYPE_MAX_NUM] =3D { > ((ptype & RTE_PTYPE_L4_FRAG) !=3D RTE_PTYPE_L4_FRAG) && \ > (RTE_ETH_IS_TUNNEL_PKT(ptype) =3D=3D 0)) > > +/* GRO with extension headers is not supported */ > +#define IS_IPV6_TCP_PKT(ptype) (RTE_ETH_IS_IPV6_HDR(ptype) && \ > + ((ptype & RTE_PTYPE_L4_TCP) =3D=3D RTE_PTYPE_L4_TCP) && \ > + ((ptype & RTE_PTYPE_L4_FRAG) !=3D RTE_PTYPE_L4_FRAG) && \ > + (RTE_ETH_IS_TUNNEL_PKT(ptype) =3D=3D 0)) > + > #define IS_IPV4_UDP_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \ > ((ptype & RTE_PTYPE_L4_UDP) =3D=3D RTE_PTYPE_L4_UDP) && \ > (RTE_ETH_IS_TUNNEL_PKT(ptype) =3D=3D 0)) > @@ -147,7 +156,11 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > /* allocate a reassembly table for TCP/IPv4 GRO */ > struct gro_tcp4_tbl tcp_tbl; > struct gro_tcp4_flow tcp_flows[RTE_GRO_MAX_BURST_ITEM_NUM]; > - struct gro_tcp4_item tcp_items[RTE_GRO_MAX_BURST_ITEM_NUM] =3D {{= 0} > }; > + struct gro_tcp_item tcp_items[RTE_GRO_MAX_BURST_ITEM_NUM] =3D {{0= } }; > + > + struct gro_tcp6_tbl tcp6_tbl; > + struct gro_tcp6_flow tcp6_flows[RTE_GRO_MAX_BURST_ITEM_NUM]; > + struct gro_tcp_item tcp6_items[RTE_GRO_MAX_BURST_ITEM_NUM] =3D {{= 0} > }; > > /* allocate a reassembly table for UDP/IPv4 GRO */ > struct gro_udp4_tbl udp_tbl; > @@ -171,10 +184,10 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > int32_t ret; > uint16_t i, unprocess_num =3D 0, nb_after_gro =3D nb_pkts; > uint8_t do_tcp4_gro =3D 0, do_vxlan_tcp_gro =3D 0, do_udp4_gro = =3D 0, > - do_vxlan_udp_gro =3D 0; > + do_vxlan_udp_gro =3D 0, do_tcp6_gro =3D 0; > > if (unlikely((param->gro_types & (RTE_GRO_IPV4_VXLAN_TCP_IPV4 | > - RTE_GRO_TCP_IPV4 | > + RTE_GRO_TCP_IPV4 | > RTE_GRO_TCP_IPV6 | > RTE_GRO_IPV4_VXLAN_UDP_IPV4 | > RTE_GRO_UDP_IPV4)) =3D=3D 0)) > return nb_pkts; > @@ -236,6 +249,18 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > do_udp4_gro =3D 1; > } > > + if (param->gro_types & RTE_GRO_TCP_IPV6) { > + for (i =3D 0; i < item_num; i++) > + tcp6_flows[i].start_index =3D INVALID_ARRAY_INDEX= ; > + > + tcp6_tbl.flows =3D tcp6_flows; > + tcp6_tbl.items =3D tcp6_items; > + tcp6_tbl.flow_num =3D 0; > + tcp6_tbl.item_num =3D 0; > + tcp6_tbl.max_flow_num =3D item_num; > + tcp6_tbl.max_item_num =3D item_num; > + do_tcp6_gro =3D 1; > + } > > for (i =3D 0; i < nb_pkts; i++) { > /* > @@ -276,6 +301,14 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > nb_after_gro--; > else if (ret < 0) > unprocess_pkts[unprocess_num++] =3D pkts[= i]; > + } else if (IS_IPV6_TCP_PKT(pkts[i]->packet_type) && > + do_tcp6_gro) { > + ret =3D gro_tcp6_reassemble(pkts[i], &tcp6_tbl, 0= ); > + if (ret > 0) > + /* merge successfully */ > + nb_after_gro--; > + else if (ret < 0) > + unprocess_pkts[unprocess_num++] =3D pkts[= i]; > } else > unprocess_pkts[unprocess_num++] =3D pkts[i]; > } > @@ -283,9 +316,17 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > if ((nb_after_gro < nb_pkts) > || (unprocess_num < nb_pkts)) { > i =3D 0; > + /* Copy unprocessed packets */ > + if (unprocess_num > 0) { > + memcpy(&pkts[i], unprocess_pkts, > + sizeof(struct rte_mbuf *) * > + unprocess_num); > + i =3D unprocess_num; > + } > + > /* Flush all packets from the tables */ > if (do_vxlan_tcp_gro) { > - i =3D > gro_vxlan_tcp4_tbl_timeout_flush(&vxlan_tcp_tbl, > + i +=3D > gro_vxlan_tcp4_tbl_timeout_flush(&vxlan_tcp_tbl, > 0, pkts, nb_pkts); > } > > @@ -304,13 +345,11 @@ rte_gro_reassemble_burst(struct rte_mbuf **pkts, > i +=3D gro_udp4_tbl_timeout_flush(&udp_tbl, 0, > &pkts[i], nb_pkts - i); > } > - /* Copy unprocessed packets */ > - if (unprocess_num > 0) { > - memcpy(&pkts[i], unprocess_pkts, > - sizeof(struct rte_mbuf *) * > - unprocess_num); > + > + if (do_tcp6_gro) { > + i +=3D gro_tcp6_tbl_timeout_flush(&tcp6_tbl, 0, > + &pkts[i], nb_pkts - i); > } > - nb_after_gro =3D i + unprocess_num; > } > > return nb_after_gro; > @@ -323,13 +362,13 @@ rte_gro_reassemble(struct rte_mbuf **pkts, > { > struct rte_mbuf *unprocess_pkts[nb_pkts]; > struct gro_ctx *gro_ctx =3D ctx; > - void *tcp_tbl, *udp_tbl, *vxlan_tcp_tbl, *vxlan_udp_tbl; > + void *tcp_tbl, *udp_tbl, *vxlan_tcp_tbl, *vxlan_udp_tbl, *tcp6_tb= l; > uint64_t current_time; > uint16_t i, unprocess_num =3D 0; > - uint8_t do_tcp4_gro, do_vxlan_tcp_gro, do_udp4_gro, > do_vxlan_udp_gro; > + uint8_t do_tcp4_gro, do_vxlan_tcp_gro, do_udp4_gro, > do_vxlan_udp_gro, do_tcp6_gro; > > if (unlikely((gro_ctx->gro_types & (RTE_GRO_IPV4_VXLAN_TCP_IPV4 | > - RTE_GRO_TCP_IPV4 | > + RTE_GRO_TCP_IPV4 | > RTE_GRO_TCP_IPV6 | > RTE_GRO_IPV4_VXLAN_UDP_IPV4 | > RTE_GRO_UDP_IPV4)) =3D=3D 0)) > return nb_pkts; > @@ -338,6 +377,7 @@ rte_gro_reassemble(struct rte_mbuf **pkts, > vxlan_tcp_tbl =3D gro_ctx->tbls[RTE_GRO_IPV4_VXLAN_TCP_IPV4_INDEX= ]; > udp_tbl =3D gro_ctx->tbls[RTE_GRO_UDP_IPV4_INDEX]; > vxlan_udp_tbl =3D gro_ctx->tbls[RTE_GRO_IPV4_VXLAN_UDP_IPV4_INDEX= ]; > + tcp6_tbl =3D gro_ctx->tbls[RTE_GRO_TCP_IPV6_INDEX]; > > do_tcp4_gro =3D (gro_ctx->gro_types & RTE_GRO_TCP_IPV4) =3D=3D > RTE_GRO_TCP_IPV4; > @@ -347,6 +387,7 @@ rte_gro_reassemble(struct rte_mbuf **pkts, > RTE_GRO_UDP_IPV4; > do_vxlan_udp_gro =3D (gro_ctx->gro_types & > RTE_GRO_IPV4_VXLAN_UDP_IPV4) =3D=3D > RTE_GRO_IPV4_VXLAN_UDP_IPV4; > + do_tcp6_gro =3D (gro_ctx->gro_types & RTE_GRO_TCP_IPV6) =3D=3D > RTE_GRO_TCP_IPV6; > > current_time =3D rte_rdtsc(); > > @@ -371,6 +412,11 @@ rte_gro_reassemble(struct rte_mbuf **pkts, > if (gro_udp4_reassemble(pkts[i], udp_tbl, > current_time) < 0) > unprocess_pkts[unprocess_num++] =3D pkts[= i]; > + } else if (IS_IPV6_TCP_PKT(pkts[i]->packet_type) && > + do_tcp6_gro) { > + if (gro_tcp6_reassemble(pkts[i], tcp6_tbl, > + current_time) < 0) > + unprocess_pkts[unprocess_num++] =3D pkts[= i]; > } else > unprocess_pkts[unprocess_num++] =3D pkts[i]; > } > @@ -426,6 +472,15 @@ rte_gro_timeout_flush(void *ctx, > gro_ctx->tbls[RTE_GRO_UDP_IPV4_INDEX], > flush_timestamp, > &out[num], left_nb_out); > + left_nb_out =3D max_nb_out - num; > + } > + > + if ((gro_types & RTE_GRO_TCP_IPV6) && left_nb_out > 0) { > + num +=3D gro_tcp6_tbl_timeout_flush( > + gro_ctx->tbls[RTE_GRO_TCP_IPV6_INDEX], > + flush_timestamp, > + &out[num], left_nb_out); > + > } > > return num; > diff --git a/lib/gro/rte_gro.h b/lib/gro/rte_gro.h > index 9f9ed4935a..c83dfd9ad1 100644 > --- a/lib/gro/rte_gro.h > +++ b/lib/gro/rte_gro.h > @@ -38,6 +38,9 @@ extern "C" { > #define RTE_GRO_IPV4_VXLAN_UDP_IPV4_INDEX 3 > #define RTE_GRO_IPV4_VXLAN_UDP_IPV4 (1ULL << > RTE_GRO_IPV4_VXLAN_UDP_IPV4_INDEX) > /**< VxLAN UDP/IPv4 GRO flag. */ > +#define RTE_GRO_TCP_IPV6_INDEX 4 > +#define RTE_GRO_TCP_IPV6 (1ULL << RTE_GRO_TCP_IPV6_INDEX) > +/**< TCP/IPv6 GRO flag. */ > > /** > * Structure used to create GRO context objects or used to pass > -- > 2.25.1 > Hi Jiyau, I have updated the review comments. Tested GRO for both v4 and >> v6. I will update the generic_receive_offload_lib.rst and release note = in >> subsequent change. Would be great if you can review the current changes = by >> then. >> > --000000000000b205c405fded8460 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 PGRpdiBkaXI9Imx0ciI+PGRpdiBkaXI9Imx0ciI+PGJyPjwvZGl2Pjxicj48ZGl2IGNsYXNzPSJn bWFpbF9xdW90ZSI+PGRpdiBkaXI9Imx0ciIgY2xhc3M9ImdtYWlsX2F0dHIiPk9uIE1vbiwgSnVu IDEyLCAyMDIzIGF0IDU6MDHigK9QTSBLdW1hcmEgUGFyYW1lc2h3YXJhbiAmbHQ7PGEgaHJlZj0i bWFpbHRvOmt1bWFyYXBhcmFtZXNoOTJAZ21haWwuY29tIj5rdW1hcmFwYXJhbWVzaDkyQGdtYWls LmNvbTwvYT4mZ3Q7IHdyb3RlOjxicj48L2Rpdj48YmxvY2txdW90ZSBjbGFzcz0iZ21haWxfcXVv dGUiIHN0eWxlPSJtYXJnaW46MHB4IDBweCAwcHggMC44ZXg7Ym9yZGVyLWxlZnQ6MXB4IHNvbGlk IHJnYigyMDQsMjA0LDIwNCk7cGFkZGluZy1sZWZ0OjFleCI+VGhlIHBhdGNoIGFkZHMgR1JPIHN1 cHBvcnQgZm9yIFRDUC9pcHY2IHBhY2tldHMuIFRoaXMgZG9lcyBub3Q8YnI+DQppbmNsdWRlIHRo ZSBzdXBwb3J0IGZvciB2eGxhbiwgdWRwIGlwdjYgcGFja2V0cy48YnI+DQo8YnI+DQpTaWduZWQt b2ZmLWJ5OiBLdW1hcmEgUGFyYW1lc2h3YXJhbiAmbHQ7PGEgaHJlZj0ibWFpbHRvOmt1bWFyYXBh cmFtZXNoOTJAZ21haWwuY29tIiB0YXJnZXQ9Il9ibGFuayI+a3VtYXJhcGFyYW1lc2g5MkBnbWFp bC5jb208L2E+Jmd0Ozxicj4NCi0tLTxicj4NCnYxOjxicj4NCsKgIMKgIMKgIMKgICogQ2hhbmdl cyB0byBzdXBwb3J0IEdSTyBmb3IgVENQL2lwdjYgcGFja2V0cy4gVGhpcyBkb2VzIG5vdCBpbmNs dWRlPGJyPg0KwqAgwqAgwqAgwqAgwqAgdnhsYW4gY2hhbmdlcy4gPGJyPg0KwqAgwqAgwqAgwqAg KiBUaGUgR1JPIGlzIHBlcmZvcm1lZCBvbmx5IGZvciBpcHY2IHBhY2tldHMgdGhhdCBkb2VzIG5v dCBjb250YWluIDxicj4NCsKgIMKgIMKgIMKgIMKgZXh0ZW5zaW9uIGhlYWRlcnMuIDxicj4NCsKg IMKgIMKgIMKgICogVGhlIGxvZ2ljIGZvciB0aGUgVENQIGNvYWxlc2NpbmcgcmVtYWlucyB0aGUg c2FtZSwgaW4gaXB2NiBoZWFkZXIgPGJyPg0KwqAgwqAgwqAgwqAgwqAgdGhlIHNvdXJjZSBhZGRy ZXNzLCBkZXN0aW5hdGlvbiBhZGRyZXNzLCBmbG93IGxhYmVsLCB2ZXJzaW9uIGZpZWxkcyA8YnI+ DQrCoCDCoCDCoCDCoCDCoCBhcmUgZXhwZWN0ZWQgdG8gYmUgdGhlIHNhbWUuIDxicj4NCsKgIMKg IMKgIMKgICogUmUtb3JnYW5pc2VkIHRoZSBjb2RlIHRvIHJldXNlIGNlcnRhaW4gdGNwIGZ1bmN0 aW9ucyBmb3IgYm90aCBpcHY0IGFuZCA8YnI+DQrCoCDCoCDCoCDCoCDCoCBpcHY2IGZsb3dzLjxi cj4NCnYyOjxicj4NCsKgIMKgIMKgIMKgICogRml4IGNvbW1lbnRzIGluIGdyb190Y3A2LmggaGVh ZGVyIGZpbGUuIDxicj4NCjxicj4NCnYzOjxicj4NCsKgIMKgIMKgIMKgICogQWRkZXJlc3MgcmV2 aWV3IGNvbW1lbnRzIHRvIGZpeCBjb2RlIGR1cGxpY2F0aW9uIGZvciB2NCBhbmQgdjY8YnI+DQo8 YnI+DQp2NDo8YnI+DQrCoCDCoCDCoCDCoCAqIEFkZHJlc3NlcyByZXZpZXcgY29tbWVudHMgZm9y IHYzLCBkbyBub3QgdXNlIGNhbGxiYWNrcyA8YnI+DQo8YnI+DQp2NTo8YnI+DQrCoCDCoCDCoCDC oCAqIEFkZHJlc3MgcmV2aWV3IGNvbW1lbnRzPGJyPg0KPGJyPg0KdjY6PGJyPg0KwqAgwqAgwqAg wqAgKiBGaXggd2FybmluZyBhbmQgY29kaW5nIHN0eWxlIGlzc3Vlczxicj4NCjxicj4NCnY3Ojxi cj4NCsKgIMKgIMKgIMKgICogRml4IGJ1aWxkIGNvbXBpbGF0aW9uIGlzc3VlPGJyPg0KwqBsaWIv Z3JvL2dyb190Y3A0LmPCoCDCoCDCoCDCoCDCoHwgMTc4ICsrKysrKy0tLS0tLS0tLS0tLS0tLS0t LS08YnI+DQrCoGxpYi9ncm8vZ3JvX3RjcDQuaMKgIMKgIMKgIMKgIMKgfCAxNzAgKy0tLS0tLS0t LS0tLS0tLS0tLS0tLS08YnI+DQrCoGxpYi9ncm8vZ3JvX3RjcDYuY8KgIMKgIMKgIMKgIMKgfCAy NjcgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKzxicj4NCsKgbGliL2dyby9n cm9fdGNwNi5owqAgwqAgwqAgwqAgwqB8IDE2MSArKysrKysrKysrKysrKysrKysrKysrPGJyPg0K wqBsaWIvZ3JvL2dyb190Y3BfaW50ZXJuYWwuYyB8IDEyOCArKysrKysrKysrKysrKysrKys8YnI+ DQrCoGxpYi9ncm8vZ3JvX3RjcF9pbnRlcm5hbC5oIHwgMjEyICsrKysrKysrKysrKysrKysrKysr KysrKysrKysrPGJyPg0KwqBsaWIvZ3JvL2dyb192eGxhbl90Y3A0LmPCoCDCoHzCoCAyMyArKy0t PGJyPg0KwqBsaWIvZ3JvL2dyb192eGxhbl90Y3A0LmjCoCDCoHzCoCDCoDMgKy08YnI+DQrCoGxp Yi9ncm8vbWVzb24uYnVpbGTCoCDCoCDCoCDCoCB8wqAgwqAyICs8YnI+DQrCoGxpYi9ncm8vcnRl X2dyby5jwqAgwqAgwqAgwqAgwqAgfMKgIDgzICsrKysrKysrKystLTxicj4NCsKgbGliL2dyby9y dGVfZ3JvLmjCoCDCoCDCoCDCoCDCoCB8wqAgwqAzICs8YnI+DQrCoDExIGZpbGVzIGNoYW5nZWQs IDg5NyBpbnNlcnRpb25zKCspLCAzMzMgZGVsZXRpb25zKC0pPGJyPg0KwqBjcmVhdGUgbW9kZSAx MDA2NDQgbGliL2dyby9ncm9fdGNwNi5jPGJyPg0KwqBjcmVhdGUgbW9kZSAxMDA2NDQgbGliL2dy by9ncm9fdGNwNi5oPGJyPg0KwqBjcmVhdGUgbW9kZSAxMDA2NDQgbGliL2dyby9ncm9fdGNwX2lu dGVybmFsLmM8YnI+DQrCoGNyZWF0ZSBtb2RlIDEwMDY0NCBsaWIvZ3JvL2dyb190Y3BfaW50ZXJu YWwuaDxicj4NCjxicj4NCmRpZmYgLS1naXQgYS9saWIvZ3JvL2dyb190Y3A0LmMgYi9saWIvZ3Jv L2dyb190Y3A0LmM8YnI+DQppbmRleCAwMDE0MDk2ZTYzLi40MmZlZTc4ZjMwIDEwMDY0NDxicj4N Ci0tLSBhL2xpYi9ncm8vZ3JvX3RjcDQuYzxicj4NCisrKyBiL2xpYi9ncm8vZ3JvX3RjcDQuYzxi cj4NCkBAIC0zMCw3ICszMCw3IEBAIGdyb190Y3A0X3RibF9jcmVhdGUodWludDE2X3Qgc29ja2V0 X2lkLDxicj4NCsKgIMKgIMKgIMKgIGlmICh0YmwgPT0gTlVMTCk8YnI+DQrCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCByZXR1cm4gTlVMTDs8YnI+DQo8YnI+DQotwqAgwqAgwqAgwqBzaXplID0gc2l6 ZW9mKHN0cnVjdCBncm9fdGNwNF9pdGVtKSAqIGVudHJpZXNfbnVtOzxicj4NCivCoCDCoCDCoCDC oHNpemUgPSBzaXplb2Yoc3RydWN0IGdyb190Y3BfaXRlbSkgKiBlbnRyaWVzX251bTs8YnI+DQrC oCDCoCDCoCDCoCB0YmwtJmd0O2l0ZW1zID0gcnRlX3ptYWxsb2Nfc29ja2V0KF9fZnVuY19fLDxi cj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNpemUsPGJyPg0KwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgUlRFX0NBQ0hFX0xJTkVfU0laRSw8YnI+DQpA QCAtNzEsMTggKzcxLDYgQEAgZ3JvX3RjcDRfdGJsX2Rlc3Ryb3kodm9pZCAqdGJsKTxicj4NCsKg IMKgIMKgIMKgIHJ0ZV9mcmVlKHRjcF90YmwpOzxicj4NCsKgfTxicj4NCjxicj4NCi1zdGF0aWMg aW5saW5lIHVpbnQzMl90PGJyPg0KLWZpbmRfYW5fZW1wdHlfaXRlbShzdHJ1Y3QgZ3JvX3RjcDRf dGJsICp0YmwpPGJyPg0KLXs8YnI+DQotwqAgwqAgwqAgwqB1aW50MzJfdCBpOzxicj4NCi3CoCDC oCDCoCDCoHVpbnQzMl90IG1heF9pdGVtX251bSA9IHRibC0mZ3Q7bWF4X2l0ZW1fbnVtOzxicj4N Ci08YnI+DQotwqAgwqAgwqAgwqBmb3IgKGkgPSAwOyBpICZsdDsgbWF4X2l0ZW1fbnVtOyBpKysp PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKHRibC0mZ3Q7aXRlbXNbaV0uZmlyc3Rz ZWcgPT0gTlVMTCk8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1 cm4gaTs8YnI+DQotwqAgwqAgwqAgwqByZXR1cm4gSU5WQUxJRF9BUlJBWV9JTkRFWDs8YnI+DQot fTxicj4NCi08YnI+DQrCoHN0YXRpYyBpbmxpbmUgdWludDMyX3Q8YnI+DQrCoGZpbmRfYW5fZW1w dHlfZmxvdyhzdHJ1Y3QgZ3JvX3RjcDRfdGJsICp0YmwpPGJyPg0KwqB7PGJyPg0KQEAgLTk1LDU2 ICs4Myw2IEBAIGZpbmRfYW5fZW1wdHlfZmxvdyhzdHJ1Y3QgZ3JvX3RjcDRfdGJsICp0YmwpPGJy Pg0KwqAgwqAgwqAgwqAgcmV0dXJuIElOVkFMSURfQVJSQVlfSU5ERVg7PGJyPg0KwqB9PGJyPg0K PGJyPg0KLXN0YXRpYyBpbmxpbmUgdWludDMyX3Q8YnI+DQotaW5zZXJ0X25ld19pdGVtKHN0cnVj dCBncm9fdGNwNF90YmwgKnRibCw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzdHJ1Y3Qg cnRlX21idWYgKnBrdCw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50NjRfdCBzdGFy dF90aW1lLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90IHByZXZfaWR4LDxi cj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRfc2VxLDxicj4NCi3CoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGlwX2lkLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDC oCDCoCDCoHVpbnQ4X3QgaXNfYXRvbWljKTxicj4NCi17PGJyPg0KLcKgIMKgIMKgIMKgdWludDMy X3QgaXRlbV9pZHg7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoGl0ZW1faWR4ID0gZmluZF9hbl9l bXB0eV9pdGVtKHRibCk7PGJyPg0KLcKgIMKgIMKgIMKgaWYgKGl0ZW1faWR4ID09IElOVkFMSURf QVJSQVlfSU5ERVgpPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIElOVkFMSURf QVJSQVlfSU5ERVg7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbXNbaXRlbV9p ZHhdLmZpcnN0c2VnID0gcGt0Ozxicj4NCi3CoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbXNbaXRlbV9p ZHhdLmxhc3RzZWcgPSBydGVfcGt0bWJ1Zl9sYXN0c2VnKHBrdCk7PGJyPg0KLcKgIMKgIMKgIMKg dGJsLSZndDtpdGVtc1tpdGVtX2lkeF0uc3RhcnRfdGltZSA9IHN0YXJ0X3RpbWU7PGJyPg0KLcKg IMKgIMKgIMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0ubmV4dF9wa3RfaWR4ID0gSU5WQUxJRF9B UlJBWV9JTkRFWDs8YnI+DQotwqAgwqAgwqAgwqB0YmwtJmd0O2l0ZW1zW2l0ZW1faWR4XS5zZW50 X3NlcSA9IHNlbnRfc2VxOzxicj4NCi3CoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbXNbaXRlbV9pZHhd LmlwX2lkID0gaXBfaWQ7PGJyPg0KLcKgIMKgIMKgIMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0u bmJfbWVyZ2VkID0gMTs8YnI+DQotwqAgwqAgwqAgwqB0YmwtJmd0O2l0ZW1zW2l0ZW1faWR4XS5p c19hdG9taWMgPSBpc19hdG9taWM7PGJyPg0KLcKgIMKgIMKgIMKgdGJsLSZndDtpdGVtX251bSsr Ozxicj4NCi08YnI+DQotwqAgwqAgwqAgwqAvKiBpZiB0aGUgcHJldmlvdXMgcGFja2V0IGV4aXN0 cywgY2hhaW4gdGhlbSB0b2dldGhlci4gKi88YnI+DQotwqAgwqAgwqAgwqBpZiAocHJldl9pZHgg IT0gSU5WQUxJRF9BUlJBWV9JTkRFWCkgezxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRi bC0mZ3Q7aXRlbXNbaXRlbV9pZHhdLm5leHRfcGt0X2lkeCA9PGJyPg0KLcKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgdGJsLSZndDtpdGVtc1twcmV2X2lkeF0ubmV4dF9wa3RfaWR4 Ozxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbXNbcHJldl9pZHhdLm5l eHRfcGt0X2lkeCA9IGl0ZW1faWR4Ozxicj4NCi3CoCDCoCDCoCDCoH08YnI+DQotPGJyPg0KLcKg IMKgIMKgIMKgcmV0dXJuIGl0ZW1faWR4Ozxicj4NCi19PGJyPg0KLTxicj4NCi1zdGF0aWMgaW5s aW5lIHVpbnQzMl90PGJyPg0KLWRlbGV0ZV9pdGVtKHN0cnVjdCBncm9fdGNwNF90YmwgKnRibCwg dWludDMyX3QgaXRlbV9pZHgsPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDMyX3Qg cHJldl9pdGVtX2lkeCk8YnI+DQotezxicj4NCi3CoCDCoCDCoCDCoHVpbnQzMl90IG5leHRfaWR4 ID0gdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0ubmV4dF9wa3RfaWR4Ozxicj4NCi08YnI+DQotwqAg wqAgwqAgwqAvKiBOVUxMIGluZGljYXRlcyBhbiBlbXB0eSBpdGVtICovPGJyPg0KLcKgIMKgIMKg IMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0uZmlyc3RzZWcgPSBOVUxMOzxicj4NCi3CoCDCoCDC oCDCoHRibC0mZ3Q7aXRlbV9udW0tLTs8YnI+DQotwqAgwqAgwqAgwqBpZiAocHJldl9pdGVtX2lk eCAhPSBJTlZBTElEX0FSUkFZX0lOREVYKTxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRi bC0mZ3Q7aXRlbXNbcHJldl9pdGVtX2lkeF0ubmV4dF9wa3RfaWR4ID0gbmV4dF9pZHg7PGJyPg0K LTxicj4NCi3CoCDCoCDCoCDCoHJldHVybiBuZXh0X2lkeDs8YnI+DQotfTxicj4NCi08YnI+DQrC oHN0YXRpYyBpbmxpbmUgdWludDMyX3Q8YnI+DQrCoGluc2VydF9uZXdfZmxvdyhzdHJ1Y3QgZ3Jv X3RjcDRfdGJsICp0YmwsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3RydWN0IHRjcDRf Zmxvd19rZXkgKnNyYyw8YnI+DQpAQCAtMTU5LDEzICs5NywxMCBAQCBpbnNlcnRfbmV3X2Zsb3co c3RydWN0IGdyb190Y3A0X3RibCAqdGJsLDxicj4NCjxicj4NCsKgIMKgIMKgIMKgIGRzdCA9ICZh bXA7KHRibC0mZ3Q7Zmxvd3NbZmxvd19pZHhdLmtleSk7PGJyPg0KPGJyPg0KLcKgIMKgIMKgIMKg cnRlX2V0aGVyX2FkZHJfY29weSgmYW1wOyhzcmMtJmd0O2V0aF9zYWRkciksICZhbXA7KGRzdC0m Z3Q7ZXRoX3NhZGRyKSk7PGJyPg0KLcKgIMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJfY29weSgmYW1w OyhzcmMtJmd0O2V0aF9kYWRkciksICZhbXA7KGRzdC0mZ3Q7ZXRoX2RhZGRyKSk7PGJyPg0KK8Kg IMKgIMKgIMKgQVNTSUdOX0NPTU1PTl9UQ1BfS0VZKCgmYW1wO3NyYy0mZ3Q7Y21uX2tleSksICgm YW1wO2RzdC0mZ3Q7Y21uX2tleSkpOzxicj4NCis8YnI+DQrCoCDCoCDCoCDCoCBkc3QtJmd0O2lw X3NyY19hZGRyID0gc3JjLSZndDtpcF9zcmNfYWRkcjs8YnI+DQrCoCDCoCDCoCDCoCBkc3QtJmd0 O2lwX2RzdF9hZGRyID0gc3JjLSZndDtpcF9kc3RfYWRkcjs8YnI+DQotwqAgwqAgwqAgwqBkc3Qt Jmd0O3JlY3ZfYWNrID0gc3JjLSZndDtyZWN2X2Fjazs8YnI+DQotwqAgwqAgwqAgwqBkc3QtJmd0 O3NyY19wb3J0ID0gc3JjLSZndDtzcmNfcG9ydDs8YnI+DQotwqAgwqAgwqAgwqBkc3QtJmd0O2Rz dF9wb3J0ID0gc3JjLSZndDtkc3RfcG9ydDs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCB0YmwtJmd0 O2Zsb3dzW2Zsb3dfaWR4XS5zdGFydF9pbmRleCA9IGl0ZW1faWR4Ozxicj4NCsKgIMKgIMKgIMKg IHRibC0mZ3Q7Zmxvd19udW0rKzs8YnI+DQpAQCAtMTczLDIxICsxMDgsNiBAQCBpbnNlcnRfbmV3 X2Zsb3coc3RydWN0IGdyb190Y3A0X3RibCAqdGJsLDxicj4NCsKgIMKgIMKgIMKgIHJldHVybiBm bG93X2lkeDs8YnI+DQrCoH08YnI+DQo8YnI+DQotLyo8YnI+DQotICogdXBkYXRlIHRoZSBwYWNr ZXQgbGVuZ3RoIGZvciB0aGUgZmx1c2hlZCBwYWNrZXQuPGJyPg0KLSAqLzxicj4NCi1zdGF0aWMg aW5saW5lIHZvaWQ8YnI+DQotdXBkYXRlX2hlYWRlcihzdHJ1Y3QgZ3JvX3RjcDRfaXRlbSAqaXRl bSk8YnI+DQotezxicj4NCi3CoCDCoCDCoCDCoHN0cnVjdCBydGVfaXB2NF9oZHIgKmlwdjRfaGRy Ozxicj4NCi3CoCDCoCDCoCDCoHN0cnVjdCBydGVfbWJ1ZiAqcGt0ID0gaXRlbS0mZ3Q7Zmlyc3Rz ZWc7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoGlwdjRfaGRyID0gKHN0cnVjdCBydGVfaXB2NF9o ZHIgKikocnRlX3BrdG1idWZfbXRvZChwa3QsIGNoYXIgKikgKzxicj4NCi3CoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdC0mZ3Q7bDJfbGVuKTs8YnI+DQotwqAgwqAgwqAgwqBp cHY0X2hkci0mZ3Q7dG90YWxfbGVuZ3RoID0gcnRlX2NwdV90b19iZV8xNihwa3QtJmd0O3BrdF9s ZW4gLTxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdC0mZ3Q7bDJf bGVuKTs8YnI+DQotfTxicj4NCi08YnI+DQrCoGludDMyX3Q8YnI+DQrCoGdyb190Y3A0X3JlYXNz ZW1ibGUoc3RydWN0IHJ0ZV9tYnVmICpwa3QsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg c3RydWN0IGdyb190Y3A0X3RibCAqdGJsLDxicj4NCkBAIC0yMDIsOSArMTIyLDggQEAgZ3JvX3Rj cDRfcmVhc3NlbWJsZShzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQrCoCDCoCDCoCDCoCB1aW50 OF90IGlzX2F0b21pYzs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCBzdHJ1Y3QgdGNwNF9mbG93X2tl eSBrZXk7PGJyPg0KLcKgIMKgIMKgIMKgdWludDMyX3QgY3VyX2lkeCwgcHJldl9pZHgsIGl0ZW1f aWR4Ozxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IGl0ZW1faWR4Ozxicj4NCsKgIMKgIMKgIMKg IHVpbnQzMl90IGksIG1heF9mbG93X251bSwgcmVtYWluaW5nX2Zsb3dfbnVtOzxicj4NCi3CoCDC oCDCoCDCoGludCBjbXA7PGJyPg0KwqAgwqAgwqAgwqAgdWludDhfdCBmaW5kOzxicj4NCjxicj4N CsKgIMKgIMKgIMKgIC8qPGJyPg0KQEAgLTIxNiw3ICsxMzUsNyBAQCBncm9fdGNwNF9yZWFzc2Vt YmxlKHN0cnVjdCBydGVfbWJ1ZiAqcGt0LDxicj4NCjxicj4NCsKgIMKgIMKgIMKgIGV0aF9oZHIg PSBydGVfcGt0bWJ1Zl9tdG9kKHBrdCwgc3RydWN0IHJ0ZV9ldGhlcl9oZHIgKik7PGJyPg0KwqAg wqAgwqAgwqAgaXB2NF9oZHIgPSAoc3RydWN0IHJ0ZV9pcHY0X2hkciAqKSgoY2hhciAqKWV0aF9o ZHIgKyBwa3QtJmd0O2wyX2xlbik7PGJyPg0KLcKgIMKgIMKgIMKgdGNwX2hkciA9IChzdHJ1Y3Qg cnRlX3RjcF9oZHIgKikoKGNoYXIgKilpcHY0X2hkciArIHBrdC0mZ3Q7bDNfbGVuKTs8YnI+DQor wqAgwqAgwqAgwqB0Y3BfaGRyID0gcnRlX3BrdG1idWZfbXRvZF9vZmZzZXQocGt0LCBzdHJ1Y3Qg cnRlX3RjcF9oZHIgKiwgcGt0LSZndDtsMl9sZW4gKyBwa3QtJmd0O2wzX2xlbik7PGJyPg0KwqAg wqAgwqAgwqAgaGRyX2xlbiA9IHBrdC0mZ3Q7bDJfbGVuICsgcGt0LSZndDtsM19sZW4gKyBwa3Qt Jmd0O2w0X2xlbjs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCAvKjxicj4NCkBAIC0yMzAsNyArMTQ5 LDYgQEAgZ3JvX3RjcDRfcmVhc3NlbWJsZShzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQrCoCDC oCDCoCDCoCBpcF90bGVuID0gcnRlX2JlX3RvX2NwdV8xNihpcHY0X2hkci0mZ3Q7dG90YWxfbGVu Z3RoKTs8YnI+DQrCoCDCoCDCoCDCoCBpZiAocGt0LSZndDtwa3RfbGVuICZndDsgKHVpbnQzMl90 KShpcF90bGVuICsgcGt0LSZndDtsMl9sZW4pKTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IHJ0ZV9wa3RtYnVmX3RyaW0ocGt0LCBwa3QtJmd0O3BrdF9sZW4gLSBpcF90bGVuIC0gcGt0LSZn dDtsMl9sZW4pOzxicj4NCi08YnI+DQrCoCDCoCDCoCDCoCAvKjxicj4NCsKgIMKgIMKgIMKgIMKg KiBEb24mIzM5O3QgcHJvY2VzcyB0aGUgcGFja2V0IHdob3NlIHBheWxvYWQgbGVuZ3RoIGlzIGxl c3MgdGhhbiBvcjxicj4NCsKgIMKgIMKgIMKgIMKgKiBlcXVhbCB0byAwLjxicj4NCkBAIC0yMzks NiArMTU3LDEzIEBAIGdyb190Y3A0X3JlYXNzZW1ibGUoc3RydWN0IHJ0ZV9tYnVmICpwa3QsPGJy Pg0KwqAgwqAgwqAgwqAgaWYgKHRjcF9kbCAmbHQ7PSAwKTxicj4NCsKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIHJldHVybiAtMTs8YnI+DQo8YnI+DQorwqAgwqAgwqAgwqBydGVfZXRoZXJfYWRkcl9j b3B5KCZhbXA7KGV0aF9oZHItJmd0O3NyY19hZGRyKSwgJmFtcDsoa2V5LmNtbl9rZXkuZXRoX3Nh ZGRyKSk7PGJyPg0KK8KgIMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJfY29weSgmYW1wOyhldGhfaGRy LSZndDtkc3RfYWRkciksICZhbXA7KGtleS5jbW5fa2V5LmV0aF9kYWRkcikpOzxicj4NCivCoCDC oCDCoCDCoGtleS5pcF9zcmNfYWRkciA9IGlwdjRfaGRyLSZndDtzcmNfYWRkcjs8YnI+DQorwqAg wqAgwqAgwqBrZXkuaXBfZHN0X2FkZHIgPSBpcHY0X2hkci0mZ3Q7ZHN0X2FkZHI7PGJyPg0KK8Kg IMKgIMKgIMKga2V5LmNtbl9rZXkuc3JjX3BvcnQgPSB0Y3BfaGRyLSZndDtzcmNfcG9ydDs8YnI+ DQorwqAgwqAgwqAgwqBrZXkuY21uX2tleS5kc3RfcG9ydCA9IHRjcF9oZHItJmd0O2RzdF9wb3J0 Ozxicj4NCivCoCDCoCDCoCDCoGtleS5jbW5fa2V5LnJlY3ZfYWNrID0gdGNwX2hkci0mZ3Q7cmVj dl9hY2s7PGJyPg0KwqAgwqAgwqAgwqAgLyo8YnI+DQrCoCDCoCDCoCDCoCDCoCogU2F2ZSBJUHY0 IElEIGZvciB0aGUgcGFja2V0IHdob3NlIERGIGJpdCBpcyAwLiBGb3IgdGhlIHBhY2tldDxicj4N CsKgIMKgIMKgIMKgIMKgKiB3aG9zZSBERiBiaXQgaXMgMSwgSVB2NCBJRCBpcyBpZ25vcmVkLjxi cj4NCkBAIC0yNDYsMTUgKzE3MSw2IEBAIGdyb190Y3A0X3JlYXNzZW1ibGUoc3RydWN0IHJ0ZV9t YnVmICpwa3QsPGJyPg0KwqAgwqAgwqAgwqAgZnJhZ19vZmYgPSBydGVfYmVfdG9fY3B1XzE2KGlw djRfaGRyLSZndDtmcmFnbWVudF9vZmZzZXQpOzxicj4NCsKgIMKgIMKgIMKgIGlzX2F0b21pYyA9 IChmcmFnX29mZiAmYW1wOyBSVEVfSVBWNF9IRFJfREZfRkxBRykgPT0gUlRFX0lQVjRfSERSX0RG X0ZMQUc7PGJyPg0KwqAgwqAgwqAgwqAgaXBfaWQgPSBpc19hdG9taWMgPyAwIDogcnRlX2JlX3Rv X2NwdV8xNihpcHY0X2hkci0mZ3Q7cGFja2V0X2lkKTs8YnI+DQotwqAgwqAgwqAgwqBzZW50X3Nl cSA9IHJ0ZV9iZV90b19jcHVfMzIodGNwX2hkci0mZ3Q7c2VudF9zZXEpOzxicj4NCi08YnI+DQot wqAgwqAgwqAgwqBydGVfZXRoZXJfYWRkcl9jb3B5KCZhbXA7KGV0aF9oZHItJmd0O3NyY19hZGRy KSwgJmFtcDsoa2V5LmV0aF9zYWRkcikpOzxicj4NCi3CoCDCoCDCoCDCoHJ0ZV9ldGhlcl9hZGRy X2NvcHkoJmFtcDsoZXRoX2hkci0mZ3Q7ZHN0X2FkZHIpLCAmYW1wOyhrZXkuZXRoX2RhZGRyKSk7 PGJyPg0KLcKgIMKgIMKgIMKga2V5LmlwX3NyY19hZGRyID0gaXB2NF9oZHItJmd0O3NyY19hZGRy Ozxicj4NCi3CoCDCoCDCoCDCoGtleS5pcF9kc3RfYWRkciA9IGlwdjRfaGRyLSZndDtkc3RfYWRk cjs8YnI+DQotwqAgwqAgwqAgwqBrZXkuc3JjX3BvcnQgPSB0Y3BfaGRyLSZndDtzcmNfcG9ydDs8 YnI+DQotwqAgwqAgwqAgwqBrZXkuZHN0X3BvcnQgPSB0Y3BfaGRyLSZndDtkc3RfcG9ydDs8YnI+ DQotwqAgwqAgwqAgwqBrZXkucmVjdl9hY2sgPSB0Y3BfaGRyLSZndDtyZWN2X2Fjazs8YnI+DQo8 YnI+DQrCoCDCoCDCoCDCoCAvKiBTZWFyY2ggZm9yIGEgbWF0Y2hlZCBmbG93LiAqLzxicj4NCsKg IMKgIMKgIMKgIG1heF9mbG93X251bSA9IHRibC0mZ3Q7bWF4X2Zsb3dfbnVtOzxicj4NCkBAIC0y NzAsNjMgKzE4Niw0NCBAQCBncm9fdGNwNF9yZWFzc2VtYmxlKHN0cnVjdCBydGVfbWJ1ZiAqcGt0 LDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIH08YnI+DQrCoCDCoCDCoCDCoCB9PGJyPg0K PGJyPg0KLcKgIMKgIMKgIMKgLyo8YnI+DQotwqAgwqAgwqAgwqAgKiBGYWlsIHRvIGZpbmQgYSBt YXRjaGVkIGZsb3cuIEluc2VydCBhIG5ldyBmbG93IGFuZCBzdG9yZSB0aGU8YnI+DQotwqAgwqAg wqAgwqAgKiBwYWNrZXQgaW50byB0aGUgZmxvdy48YnI+DQotwqAgwqAgwqAgwqAgKi88YnI+DQrC oCDCoCDCoCDCoCBpZiAoZmluZCA9PSAwKSB7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg aXRlbV9pZHggPSBpbnNlcnRfbmV3X2l0ZW0odGJsLCBwa3QsIHN0YXJ0X3RpbWUsPGJyPg0KLcKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgSU5WQUxJRF9BUlJB WV9JTkRFWCwgc2VudF9zZXEsIGlwX2lkLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlzX2F0b21pYyk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgc2VudF9zZXEgPSBydGVfYmVfdG9fY3B1XzMyKHRjcF9oZHItJmd0O3NlbnRfc2VxKTs8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpdGVtX2lkeCA9IGluc2VydF9uZXdfdGNwX2l0 ZW0ocGt0LCB0YmwtJmd0O2l0ZW1zLCAmYW1wO3RibC0mZ3Q7aXRlbV9udW0sPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgdGJsLSZndDttYXhfaXRlbV9udW0sIHN0YXJ0X3RpbWUsPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgSU5WQUxJRF9BUlJBWV9JTkRFWCwgc2VudF9zZXEsIGlwX2lkLDxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoGlzX2F0b21pYyk7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKGl0ZW1f aWR4ID09IElOVkFMSURfQVJSQVlfSU5ERVgpPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgcmV0dXJuIC0xOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChp bnNlcnRfbmV3X2Zsb3codGJsLCAmYW1wO2tleSwgaXRlbV9pZHgpID09PGJyPg0KLcKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgSU5WQUxJRF9BUlJBWV9JTkRF WCkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoElOVkFMSURfQVJS QVlfSU5ERVgpIHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAvKjxi cj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgKiBGYWlsIHRvIGluc2Vy dCBhIG5ldyBmbG93LCBzbyBkZWxldGUgdGhlPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAqIHN0b3JlZCBwYWNrZXQuPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgICovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgZGVsZXRlX2l0ZW0odGJsLCBpdGVtX2lkeCwgSU5WQUxJRF9BUlJBWV9JTkRFWCk7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgKi88YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBkZWxldGVfdGNwX2l0ZW0odGJsLSZndDtpdGVtcywgaXRl bV9pZHgsICZhbXA7dGJsLSZndDtpdGVtX251bSwgSU5WQUxJRF9BUlJBWV9JTkRFWCk7PGJyPg0K wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuIC0xOzxicj4NCsKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIH08YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXR1cm4g MDs8YnI+DQrCoCDCoCDCoCDCoCB9PGJyPg0KPGJyPg0KLcKgIMKgIMKgIMKgLyo8YnI+DQotwqAg wqAgwqAgwqAgKiBDaGVjayBhbGwgcGFja2V0cyBpbiB0aGUgZmxvdyBhbmQgdHJ5IHRvIGZpbmQg YSBuZWlnaGJvciBmb3I8YnI+DQotwqAgwqAgwqAgwqAgKiB0aGUgaW5wdXQgcGFja2V0Ljxicj4N Ci3CoCDCoCDCoCDCoCAqLzxicj4NCi3CoCDCoCDCoCDCoGN1cl9pZHggPSB0YmwtJmd0O2Zsb3dz W2ldLnN0YXJ0X2luZGV4Ozxicj4NCi3CoCDCoCDCoCDCoHByZXZfaWR4ID0gY3VyX2lkeDs8YnI+ DQotwqAgwqAgwqAgwqBkbyB7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgY21wID0gY2hl Y2tfc2VxX29wdGlvbigmYW1wOyh0YmwtJmd0O2l0ZW1zW2N1cl9pZHhdKSwgdGNwX2hkciw8YnI+ DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzZW50X3Nl cSwgaXBfaWQsIHBrdC0mZ3Q7bDRfbGVuLCB0Y3BfZGwsIDAsPGJyPg0KLcKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaXNfYXRvbWljKTs8YnI+DQotwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBpZiAoY21wKSB7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgaWYgKG1lcmdlX3R3b190Y3A0X3BhY2tldHMoJmFtcDsodGJsLSZndDtpdGVt c1tjdXJfaWR4XSksPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcGt0LCBjbXAsIHNlbnRfc2VxLCBpcF9p ZCwgMCkpPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgcmV0dXJuIDE7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyo8 YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKiBGYWlsIHRvIG1lcmdl IHRoZSB0d28gcGFja2V0cywgYXMgdGhlIHBhY2tldDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCAqIGxlbmd0aCBpcyBncmVhdGVyIHRoYW4gdGhlIG1heCB2YWx1ZS4g U3RvcmU8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKiB0aGUgcGFj a2V0IGludG8gdGhlIGZsb3cuPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgICovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGluc2Vy dF9uZXdfaXRlbSh0YmwsIHBrdCwgc3RhcnRfdGltZSwgY3VyX2lkeCw8YnI+DQotwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBzZW50X3NlcSwgaXBfaWQsIGlzX2F0b21pYykgPT08YnI+DQotwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBJTlZBTElEX0FSUkFZ X0lOREVYKTxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoHJldHVybiAtMTs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBy ZXR1cm4gMDs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0KLcKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgcHJldl9pZHggPSBjdXJfaWR4Ozxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDC oCDCoGN1cl9pZHggPSB0YmwtJmd0O2l0ZW1zW2N1cl9pZHhdLm5leHRfcGt0X2lkeDs8YnI+DQot wqAgwqAgwqAgwqB9IHdoaWxlIChjdXJfaWR4ICE9IElOVkFMSURfQVJSQVlfSU5ERVgpOzxicj4N CivCoCDCoCDCoCDCoHJldHVybiBwcm9jZXNzX3RjcF9pdGVtKHBrdCwgdGNwX2hkciwgdGNwX2Rs LCB0YmwtJmd0O2l0ZW1zLCB0YmwtJmd0O2Zsb3dzW2ldLnN0YXJ0X2luZGV4LDxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCZhbXA7dGJsLSZndDtpdGVtX251bSwgdGJsLSZndDttYXhfaXRlbV9udW0sPGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgaXBfaWQsIGlzX2F0b21pYywgc3RhcnRfdGltZSk7PGJyPg0KK308 YnI+DQo8YnI+DQotwqAgwqAgwqAgwqAvKiBGYWlsIHRvIGZpbmQgYSBuZWlnaGJvciwgc28gc3Rv cmUgdGhlIHBhY2tldCBpbnRvIHRoZSBmbG93LiAqLzxicj4NCi3CoCDCoCDCoCDCoGlmIChpbnNl cnRfbmV3X2l0ZW0odGJsLCBwa3QsIHN0YXJ0X3RpbWUsIHByZXZfaWR4LCBzZW50X3NlcSw8YnI+ DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpcF9pZCwg aXNfYXRvbWljKSA9PSBJTlZBTElEX0FSUkFZX0lOREVYKTxicj4NCi3CoCDCoCDCoCDCoCDCoCDC oCDCoCDCoHJldHVybiAtMTs8YnI+DQorLyo8YnI+DQorICogdXBkYXRlIHRoZSBwYWNrZXQgbGVu Z3RoIGZvciB0aGUgZmx1c2hlZCBwYWNrZXQuPGJyPg0KKyAqLzxicj4NCitzdGF0aWMgaW5saW5l IHZvaWQ8YnI+DQordXBkYXRlX2hlYWRlcihzdHJ1Y3QgZ3JvX3RjcF9pdGVtICppdGVtKTxicj4N Cit7PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IHJ0ZV9pcHY0X2hkciAqaXB2NF9oZHI7PGJyPg0K K8KgIMKgIMKgIMKgc3RydWN0IHJ0ZV9tYnVmICpwa3QgPSBpdGVtLSZndDtmaXJzdHNlZzs8YnI+ DQo8YnI+DQotwqAgwqAgwqAgwqByZXR1cm4gMDs8YnI+DQorwqAgwqAgwqAgwqBpcHY0X2hkciA9 IChzdHJ1Y3QgcnRlX2lwdjRfaGRyICopKHJ0ZV9wa3RtYnVmX210b2QocGt0LCBjaGFyICopICs8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3QtJmd0O2wyX2xlbik7 PGJyPg0KK8KgIMKgIMKgIMKgaXB2NF9oZHItJmd0O3RvdGFsX2xlbmd0aCA9IHJ0ZV9jcHVfdG9f YmVfMTYocGt0LSZndDtwa3RfbGVuIC08YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBwa3QtJmd0O2wyX2xlbik7PGJyPg0KwqB9PGJyPg0KPGJyPg0KwqB1aW50MTZfdDxi cj4NCkBAIC0zNTMsNyArMjUwLDggQEAgZ3JvX3RjcDRfdGJsX3RpbWVvdXRfZmx1c2goc3RydWN0 IGdyb190Y3A0X3RibCAqdGJsLDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgKiBEZWxldGUgdGhlIHBhY2tldCBhbmQgZ2V0IHRoZSBuZXh0PGJy Pg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAqIHBh Y2tldCBpbiB0aGUgZmxvdy48YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgaiA9IGRlbGV0ZV9pdGVtKHRibCwgaiwgSU5WQUxJRF9BUlJBWV9JTkRF WCk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg aiA9IGRlbGV0ZV90Y3BfaXRlbSh0YmwtJmd0O2l0ZW1zLCBqLDxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCZhbXA7dGJsLSZndDtpdGVtX251bSwgSU5WQUxJRF9BUlJBWV9JTkRFWCk7 PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdGJs LSZndDtmbG93c1tpXS5zdGFydF9pbmRleCA9IGo7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKGogPT0gSU5WQUxJRF9BUlJBWV9JTkRFWCk8 YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCB0YmwtJmd0O2Zsb3dfbnVtLS07PGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vZ3Jv X3RjcDQuaCBiL2xpYi9ncm8vZ3JvX3RjcDQuaDxicj4NCmluZGV4IDIxMmY5N2EwNDIuLmMwMTU0 YWZhMjQgMTAwNjQ0PGJyPg0KLS0tIGEvbGliL2dyby9ncm9fdGNwNC5oPGJyPg0KKysrIGIvbGli L2dyby9ncm9fdGNwNC5oPGJyPg0KQEAgLTUsMzIgKzUsMTUgQEA8YnI+DQrCoCNpZm5kZWYgX0dS T19UQ1A0X0hfPGJyPg0KwqAjZGVmaW5lIF9HUk9fVENQNF9IXzxicj4NCjxicj4NCi0jaW5jbHVk ZSAmbHQ7cnRlX3RjcC5oJmd0Ozxicj4NCisjaW5jbHVkZSAmbHQ7Z3JvX3RjcF9pbnRlcm5hbC5o Jmd0Ozxicj4NCjxicj4NCi0jZGVmaW5lIElOVkFMSURfQVJSQVlfSU5ERVggMHhmZmZmZmZmZlVM PGJyPg0KwqAjZGVmaW5lIEdST19UQ1A0X1RCTF9NQVhfSVRFTV9OVU0gKDEwMjRVTCAqIDEwMjRV TCk8YnI+DQo8YnI+DQotLyo8YnI+DQotICogVGhlIG1heCBsZW5ndGggb2YgYSBJUHY0IHBhY2tl dCwgd2hpY2ggaW5jbHVkZXMgdGhlIGxlbmd0aCBvZiB0aGUgTDM8YnI+DQotICogaGVhZGVyLCB0 aGUgTDQgaGVhZGVyIGFuZCB0aGUgZGF0YSBwYXlsb2FkLjxicj4NCi0gKi88YnI+DQotI2RlZmlu ZSBNQVhfSVBWNF9QS1RfTEVOR1RIIFVJTlQxNl9NQVg8YnI+DQotPGJyPg0KLS8qIFRoZSBtYXhp bXVtIFRDUCBoZWFkZXIgbGVuZ3RoICovPGJyPg0KLSNkZWZpbmUgTUFYX1RDUF9ITEVOIDYwPGJy Pg0KLSNkZWZpbmUgSU5WQUxJRF9UQ1BfSERSTEVOKGxlbikgXDxicj4NCi3CoCDCoCDCoCDCoCgo KGxlbikgJmx0OyBzaXplb2Yoc3RydWN0IHJ0ZV90Y3BfaGRyKSkgfHwgKChsZW4pICZndDsgTUFY X1RDUF9ITEVOKSk8YnI+DQotPGJyPg0KLS8qIEhlYWRlciBmaWVsZHMgcmVwcmVzZW50aW5nIGEg VENQL0lQdjQgZmxvdyAqLzxicj4NCisvKiBIZWFkZXIgZmllbGRzIHJlcHJlc2VudGluZyBjb21t b24gZmllbGRzIGluIFRDUCBmbG93ICovPGJyPg0KwqBzdHJ1Y3QgdGNwNF9mbG93X2tleSB7PGJy Pg0KLcKgIMKgIMKgIMKgc3RydWN0IHJ0ZV9ldGhlcl9hZGRyIGV0aF9zYWRkcjs8YnI+DQotwqAg wqAgwqAgwqBzdHJ1Y3QgcnRlX2V0aGVyX2FkZHIgZXRoX2RhZGRyOzxicj4NCivCoCDCoCDCoCDC oHN0cnVjdCBjbW5fdGNwX2tleSBjbW5fa2V5Ozxicj4NCsKgIMKgIMKgIMKgIHVpbnQzMl90IGlw X3NyY19hZGRyOzxicj4NCsKgIMKgIMKgIMKgIHVpbnQzMl90IGlwX2RzdF9hZGRyOzxicj4NCi08 YnI+DQotwqAgwqAgwqAgwqB1aW50MzJfdCByZWN2X2Fjazs8YnI+DQotwqAgwqAgwqAgwqB1aW50 MTZfdCBzcmNfcG9ydDs8YnI+DQotwqAgwqAgwqAgwqB1aW50MTZfdCBkc3RfcG9ydDs8YnI+DQrC oH07PGJyPg0KPGJyPg0KwqBzdHJ1Y3QgZ3JvX3RjcDRfZmxvdyB7PGJyPg0KQEAgLTQyLDQyICsy NSwxMiBAQCBzdHJ1Y3QgZ3JvX3RjcDRfZmxvdyB7PGJyPg0KwqAgwqAgwqAgwqAgdWludDMyX3Qg c3RhcnRfaW5kZXg7PGJyPg0KwqB9Ozxicj4NCjxicj4NCi1zdHJ1Y3QgZ3JvX3RjcDRfaXRlbSB7 PGJyPg0KLcKgIMKgIMKgIMKgLyo8YnI+DQotwqAgwqAgwqAgwqAgKiBUaGUgZmlyc3QgTUJVRiBz ZWdtZW50IG9mIHRoZSBwYWNrZXQuIElmIHRoZSB2YWx1ZTxicj4NCi3CoCDCoCDCoCDCoCAqIGlz IE5VTEwsIGl0IG1lYW5zIHRoZSBpdGVtIGlzIGVtcHR5Ljxicj4NCi3CoCDCoCDCoCDCoCAqLzxi cj4NCi3CoCDCoCDCoCDCoHN0cnVjdCBydGVfbWJ1ZiAqZmlyc3RzZWc7PGJyPg0KLcKgIMKgIMKg IMKgLyogVGhlIGxhc3QgTUJVRiBzZWdtZW50IG9mIHRoZSBwYWNrZXQgKi88YnI+DQotwqAgwqAg wqAgwqBzdHJ1Y3QgcnRlX21idWYgKmxhc3RzZWc7PGJyPg0KLcKgIMKgIMKgIMKgLyo8YnI+DQot wqAgwqAgwqAgwqAgKiBUaGUgdGltZSB3aGVuIHRoZSBmaXJzdCBwYWNrZXQgaXMgaW5zZXJ0ZWQg aW50byB0aGUgdGFibGUuPGJyPg0KLcKgIMKgIMKgIMKgICogVGhpcyB2YWx1ZSB3b24mIzM5O3Qg YmUgdXBkYXRlZCwgZXZlbiBpZiB0aGUgcGFja2V0IGlzIG1lcmdlZDxicj4NCi3CoCDCoCDCoCDC oCAqIHdpdGggb3RoZXIgcGFja2V0cy48YnI+DQotwqAgwqAgwqAgwqAgKi88YnI+DQotwqAgwqAg wqAgwqB1aW50NjRfdCBzdGFydF90aW1lOzxicj4NCi3CoCDCoCDCoCDCoC8qPGJyPg0KLcKgIMKg IMKgIMKgICogbmV4dF9wa3RfaWR4IGlzIHVzZWQgdG8gY2hhaW4gdGhlIHBhY2tldHMgdGhhdDxi cj4NCi3CoCDCoCDCoCDCoCAqIGFyZSBpbiB0aGUgc2FtZSBmbG93IGJ1dCBjYW4mIzM5O3QgYmUg bWVyZ2VkIHRvZ2V0aGVyPGJyPg0KLcKgIMKgIMKgIMKgICogKGUuZy4gY2F1c2VkIGJ5IHBhY2tl dCByZW9yZGVyaW5nKS48YnI+DQotwqAgwqAgwqAgwqAgKi88YnI+DQotwqAgwqAgwqAgwqB1aW50 MzJfdCBuZXh0X3BrdF9pZHg7PGJyPg0KLcKgIMKgIMKgIMKgLyogVENQIHNlcXVlbmNlIG51bWJl ciBvZiB0aGUgcGFja2V0ICovPGJyPg0KLcKgIMKgIMKgIMKgdWludDMyX3Qgc2VudF9zZXE7PGJy Pg0KLcKgIMKgIMKgIMKgLyogSVB2NCBJRCBvZiB0aGUgcGFja2V0ICovPGJyPg0KLcKgIMKgIMKg IMKgdWludDE2X3QgaXBfaWQ7PGJyPg0KLcKgIMKgIMKgIMKgLyogdGhlIG51bWJlciBvZiBtZXJn ZWQgcGFja2V0cyAqLzxicj4NCi3CoCDCoCDCoCDCoHVpbnQxNl90IG5iX21lcmdlZDs8YnI+DQot wqAgwqAgwqAgwqAvKiBJbmRpY2F0ZSBpZiBJUHY0IElEIGNhbiBiZSBpZ25vcmVkICovPGJyPg0K LcKgIMKgIMKgIMKgdWludDhfdCBpc19hdG9taWM7PGJyPg0KLX07PGJyPg0KLTxicj4NCsKgLyo8 YnI+DQrCoCAqIFRDUC9JUHY0IHJlYXNzZW1ibHkgdGFibGUgc3RydWN0dXJlLjxicj4NCsKgICov PGJyPg0KwqBzdHJ1Y3QgZ3JvX3RjcDRfdGJsIHs8YnI+DQrCoCDCoCDCoCDCoCAvKiBpdGVtIGFy cmF5ICovPGJyPg0KLcKgIMKgIMKgIMKgc3RydWN0IGdyb190Y3A0X2l0ZW0gKml0ZW1zOzxicj4N CivCoCDCoCDCoCDCoHN0cnVjdCBncm9fdGNwX2l0ZW0gKml0ZW1zOzxicj4NCsKgIMKgIMKgIMKg IC8qIGZsb3cgYXJyYXkgKi88YnI+DQrCoCDCoCDCoCDCoCBzdHJ1Y3QgZ3JvX3RjcDRfZmxvdyAq Zmxvd3M7PGJyPg0KwqAgwqAgwqAgwqAgLyogY3VycmVudCBpdGVtIG51bWJlciAqLzxicj4NCkBA IC0xODYsMTIwICsxMzksOSBAQCB1aW50MzJfdCBncm9fdGNwNF90YmxfcGt0X2NvdW50KHZvaWQg KnRibCk7PGJyPg0KwqBzdGF0aWMgaW5saW5lIGludDxicj4NCsKgaXNfc2FtZV90Y3A0X2Zsb3co c3RydWN0IHRjcDRfZmxvd19rZXkgazEsIHN0cnVjdCB0Y3A0X2Zsb3dfa2V5IGsyKTxicj4NCsKg ezxicj4NCi3CoCDCoCDCoCDCoHJldHVybiAocnRlX2lzX3NhbWVfZXRoZXJfYWRkcigmYW1wO2sx LmV0aF9zYWRkciwgJmFtcDtrMi5ldGhfc2FkZHIpICZhbXA7JmFtcDs8YnI+DQotwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBydGVfaXNfc2FtZV9ldGhlcl9hZGRyKCZhbXA7azEu ZXRoX2RhZGRyLCAmYW1wO2syLmV0aF9kYWRkcikgJmFtcDsmYW1wOzxicj4NCi3CoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoChrMS5pcF9zcmNfYWRkciA9PSBrMi5pcF9zcmNfYWRk cikgJmFtcDsmYW1wOzxicj4NCivCoCDCoCDCoCDCoHJldHVybiAoKGsxLmlwX3NyY19hZGRyID09 IGsyLmlwX3NyY19hZGRyKSAmYW1wOyZhbXA7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgKGsxLmlwX2RzdF9hZGRyID09IGsyLmlwX2RzdF9hZGRyKSAmYW1wOyZhbXA7 PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgKGsxLnJlY3ZfYWNrID09 IGsyLnJlY3ZfYWNrKSAmYW1wOyZhbXA7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgKGsxLnNyY19wb3J0ID09IGsyLnNyY19wb3J0KSAmYW1wOyZhbXA7PGJyPg0KLcKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgKGsxLmRzdF9wb3J0ID09IGsyLmRzdF9w b3J0KSk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaXNfY29tbW9u X3RjcF9rZXkoJmFtcDtrMS5jbW5fa2V5LCAmYW1wO2syLmNtbl9rZXkpKTs8YnI+DQrCoH08YnI+ DQo8YnI+DQotLyo8YnI+DQotICogTWVyZ2UgdHdvIFRDUC9JUHY0IHBhY2tldHMgd2l0aG91dCB1 cGRhdGluZyBjaGVja3N1bXMuPGJyPg0KLSAqIElmIGNtcCBpcyBsYXJnZXIgdGhhbiAwLCBhcHBl bmQgdGhlIG5ldyBwYWNrZXQgdG8gdGhlPGJyPg0KLSAqIG9yaWdpbmFsIHBhY2tldC4gT3RoZXJ3 aXNlLCBwcmUtcGVuZCB0aGUgbmV3IHBhY2tldCB0bzxicj4NCi0gKiB0aGUgb3JpZ2luYWwgcGFj a2V0Ljxicj4NCi0gKi88YnI+DQotc3RhdGljIGlubGluZSBpbnQ8YnI+DQotbWVyZ2VfdHdvX3Rj cDRfcGFja2V0cyhzdHJ1Y3QgZ3JvX3RjcDRfaXRlbSAqaXRlbSw8YnI+DQotwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBpbnQgY21wLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRf c2VxLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGlwX2lkLDxicj4NCi3C oCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGwyX29mZnNldCk8YnI+DQotezxicj4NCi3C oCDCoCDCoCDCoHN0cnVjdCBydGVfbWJ1ZiAqcGt0X2hlYWQsICpwa3RfdGFpbCwgKmxhc3RzZWc7 PGJyPg0KLcKgIMKgIMKgIMKgdWludDE2X3QgaGRyX2xlbiwgbDJfbGVuOzxicj4NCi08YnI+DQot wqAgwqAgwqAgwqBpZiAoY21wICZndDsgMCkgezxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDC oHBrdF9oZWFkID0gaXRlbS0mZ3Q7Zmlyc3RzZWc7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgcGt0X3RhaWwgPSBwa3Q7PGJyPg0KLcKgIMKgIMKgIMKgfSBlbHNlIHs8YnI+DQotwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBwa3RfaGVhZCA9IHBrdDs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBwa3RfdGFpbCA9IGl0ZW0tJmd0O2ZpcnN0c2VnOzxicj4NCi3CoCDCoCDCoCDCoH08YnI+ DQotPGJyPg0KLcKgIMKgIMKgIMKgLyogY2hlY2sgaWYgdGhlIElQdjQgcGFja2V0IGxlbmd0aCBp cyBncmVhdGVyIHRoYW4gdGhlIG1heCB2YWx1ZSAqLzxicj4NCi3CoCDCoCDCoCDCoGhkcl9sZW4g PSBsMl9vZmZzZXQgKyBwa3RfaGVhZC0mZ3Q7bDJfbGVuICsgcGt0X2hlYWQtJmd0O2wzX2xlbiAr PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcGt0X2hlYWQtJmd0O2w0X2xlbjs8YnI+DQot wqAgwqAgwqAgwqBsMl9sZW4gPSBsMl9vZmZzZXQgJmd0OyAwID8gcGt0X2hlYWQtJmd0O291dGVy X2wyX2xlbiA6IHBrdF9oZWFkLSZndDtsMl9sZW47PGJyPg0KLcKgIMKgIMKgIMKgaWYgKHVubGlr ZWx5KHBrdF9oZWFkLSZndDtwa3RfbGVuIC0gbDJfbGVuICsgcGt0X3RhaWwtJmd0O3BrdF9sZW4g LTxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGhk cl9sZW4gJmd0OyBNQVhfSVBWNF9QS1RfTEVOR1RIKSk8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqByZXR1cm4gMDs8YnI+DQotPGJyPg0KLcKgIMKgIMKgIMKgLyogcmVtb3ZlIHRoZSBwYWNr ZXQgaGVhZGVyIGZvciB0aGUgdGFpbCBwYWNrZXQgKi88YnI+DQotwqAgwqAgwqAgwqBydGVfcGt0 bWJ1Zl9hZGoocGt0X3RhaWwsIGhkcl9sZW4pOzxicj4NCi08YnI+DQotwqAgwqAgwqAgwqAvKiBj aGFpbiB0d28gcGFja2V0cyB0b2dldGhlciAqLzxicj4NCi3CoCDCoCDCoCDCoGlmIChjbXAgJmd0 OyAwKSB7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaXRlbS0mZ3Q7bGFzdHNlZy0mZ3Q7 bmV4dCA9IHBrdDs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpdGVtLSZndDtsYXN0c2Vn ID0gcnRlX3BrdG1idWZfbGFzdHNlZyhwa3QpOzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDC oC8qIHVwZGF0ZSBJUCBJRCB0byB0aGUgbGFyZ2VyIHZhbHVlICovPGJyPg0KLcKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgaXRlbS0mZ3Q7aXBfaWQgPSBpcF9pZDs8YnI+DQotwqAgwqAgwqAgwqB9IGVs c2Ugezxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGxhc3RzZWcgPSBydGVfcGt0bWJ1Zl9s YXN0c2VnKHBrdCk7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbGFzdHNlZy0mZ3Q7bmV4 dCA9IGl0ZW0tJmd0O2ZpcnN0c2VnOzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW0t Jmd0O2ZpcnN0c2VnID0gcGt0Ozxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8qIHVwZGF0 ZSBzZW50X3NlcSB0byB0aGUgc21hbGxlciB2YWx1ZSAqLzxicj4NCi3CoCDCoCDCoCDCoCDCoCDC oCDCoCDCoGl0ZW0tJmd0O3NlbnRfc2VxID0gc2VudF9zZXE7PGJyPg0KLcKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgaXRlbS0mZ3Q7aXBfaWQgPSBpcF9pZDs8YnI+DQotwqAgwqAgwqAgwqB9PGJyPg0K LcKgIMKgIMKgIMKgaXRlbS0mZ3Q7bmJfbWVyZ2VkKys7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDC oC8qIHVwZGF0ZSBNQlVGIG1ldGFkYXRhIGZvciB0aGUgbWVyZ2VkIHBhY2tldCAqLzxicj4NCi3C oCDCoCDCoCDCoHBrdF9oZWFkLSZndDtuYl9zZWdzICs9IHBrdF90YWlsLSZndDtuYl9zZWdzOzxi cj4NCi3CoCDCoCDCoCDCoHBrdF9oZWFkLSZndDtwa3RfbGVuICs9IHBrdF90YWlsLSZndDtwa3Rf bGVuOzxicj4NCi08YnI+DQotwqAgwqAgwqAgwqByZXR1cm4gMTs8YnI+DQotfTxicj4NCi08YnI+ DQotLyo8YnI+DQotICogQ2hlY2sgaWYgdHdvIFRDUC9JUHY0IHBhY2tldHMgYXJlIG5laWdoYm9y cy48YnI+DQotICovPGJyPg0KLXN0YXRpYyBpbmxpbmUgaW50PGJyPg0KLWNoZWNrX3NlcV9vcHRp b24oc3RydWN0IGdyb190Y3A0X2l0ZW0gKml0ZW0sPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgc3RydWN0IHJ0ZV90Y3BfaGRyICp0Y3BoLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDC oHVpbnQzMl90IHNlbnRfc2VxLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90 IGlwX2lkLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IHRjcF9obCw8YnI+ DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCB0Y3BfZGwsPGJyPg0KLcKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgdWludDE2X3QgbDJfb2Zmc2V0LDxicj4NCi3CoCDCoCDCoCDCoCDCoCDC oCDCoCDCoHVpbnQ4X3QgaXNfYXRvbWljKTxicj4NCi17PGJyPg0KLcKgIMKgIMKgIMKgc3RydWN0 IHJ0ZV9tYnVmICpwa3Rfb3JpZyA9IGl0ZW0tJmd0O2ZpcnN0c2VnOzxicj4NCi3CoCDCoCDCoCDC oHN0cnVjdCBydGVfaXB2NF9oZHIgKmlwaF9vcmlnOzxicj4NCi3CoCDCoCDCoCDCoHN0cnVjdCBy dGVfdGNwX2hkciAqdGNwaF9vcmlnOzxicj4NCi3CoCDCoCDCoCDCoHVpbnQxNl90IGxlbiwgdGNw X2hsX29yaWc7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoGlwaF9vcmlnID0gKHN0cnVjdCBydGVf aXB2NF9oZHIgKikocnRlX3BrdG1idWZfbXRvZChwa3Rfb3JpZywgY2hhciAqKSArPGJyPg0KLcKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbDJfb2Zmc2V0ICsgcGt0X29yaWctJmd0 O2wyX2xlbik7PGJyPg0KLcKgIMKgIMKgIMKgdGNwaF9vcmlnID0gKHN0cnVjdCBydGVfdGNwX2hk ciAqKSgoY2hhciAqKWlwaF9vcmlnICsgcGt0X29yaWctJmd0O2wzX2xlbik7PGJyPg0KLcKgIMKg IMKgIMKgdGNwX2hsX29yaWcgPSBwa3Rfb3JpZy0mZ3Q7bDRfbGVuOzxicj4NCi08YnI+DQotwqAg wqAgwqAgwqAvKiBDaGVjayBpZiBUQ1Agb3B0aW9uIGZpZWxkcyBlcXVhbCAqLzxicj4NCi3CoCDC oCDCoCDCoGxlbiA9IFJURV9NQVgodGNwX2hsLCB0Y3BfaGxfb3JpZykgLSBzaXplb2Yoc3RydWN0 IHJ0ZV90Y3BfaGRyKTs8YnI+DQotwqAgwqAgwqAgwqBpZiAoKHRjcF9obCAhPSB0Y3BfaGxfb3Jp ZykgfHwgKChsZW4gJmd0OyAwKSAmYW1wOyZhbXA7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgKG1lbWNtcCh0Y3BoICsgMSwgdGNwaF9vcmlnICsg MSw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBsZW4pICE9IDApKSk8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1 cm4gMDs8YnI+DQotPGJyPg0KLcKgIMKgIMKgIMKgLyogRG9uJiMzOTt0IG1lcmdlIHBhY2tldHMg d2hvc2UgREYgYml0cyBhcmUgZGlmZmVyZW50ICovPGJyPg0KLcKgIMKgIMKgIMKgaWYgKHVubGlr ZWx5KGl0ZW0tJmd0O2lzX2F0b21pYyBeIGlzX2F0b21pYykpPGJyPg0KLcKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgcmV0dXJuIDA7PGJyPg0KLTxicj4NCi3CoCDCoCDCoCDCoC8qIGNoZWNrIGlmIHRo ZSB0d28gcGFja2V0cyBhcmUgbmVpZ2hib3JzICovPGJyPg0KLcKgIMKgIMKgIMKgbGVuID0gcGt0 X29yaWctJmd0O3BrdF9sZW4gLSBsMl9vZmZzZXQgLSBwa3Rfb3JpZy0mZ3Q7bDJfbGVuIC08YnI+ DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3Rfb3JpZy0mZ3Q7bDNfbGVuIC0gdGNwX2hsX29y aWc7PGJyPg0KLcKgIMKgIMKgIMKgaWYgKChzZW50X3NlcSA9PSBpdGVtLSZndDtzZW50X3NlcSAr IGxlbikgJmFtcDsmYW1wOyAoaXNfYXRvbWljIHx8PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgKGlwX2lkID09IGl0ZW0tJmd0O2lwX2lkICsgMSkp KTxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8qIGFwcGVuZCB0aGUgbmV3IHBhY2tldCAq Lzxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiAxOzxicj4NCi3CoCDCoCDCoCDC oGVsc2UgaWYgKChzZW50X3NlcSArIHRjcF9kbCA9PSBpdGVtLSZndDtzZW50X3NlcSkgJmFtcDsm YW1wOyAoaXNfYXRvbWljIHx8PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgKGlwX2lkICsgaXRlbS0mZ3Q7bmJfbWVyZ2VkID09IGl0ZW0tJmd0O2lw X2lkKSkpPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyogcHJlLXBlbmQgdGhlIG5ldyBw YWNrZXQgKi88YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gLTE7PGJyPg0KLTxi cj4NCi3CoCDCoCDCoCDCoHJldHVybiAwOzxicj4NCi19PGJyPg0KwqAjZW5kaWY8YnI+DQpkaWZm IC0tZ2l0IGEvbGliL2dyby9ncm9fdGNwNi5jIGIvbGliL2dyby9ncm9fdGNwNi5jPGJyPg0KbmV3 IGZpbGUgbW9kZSAxMDA2NDQ8YnI+DQppbmRleCAwMDAwMDAwMDAwLi4wZWE3Mzc0MWMxPGJyPg0K LS0tIC9kZXYvbnVsbDxicj4NCisrKyBiL2xpYi9ncm8vZ3JvX3RjcDYuYzxicj4NCkBAIC0wLDAg KzEsMjY3IEBAPGJyPg0KKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMy1DbGF1c2U8 YnI+DQorICogQ29weXJpZ2h0KGMpIDIwMTcgSW50ZWwgQ29ycG9yYXRpb248YnI+DQorICovPGJy Pg0KKzxicj4NCisjaW5jbHVkZSAmbHQ7cnRlX21hbGxvYy5oJmd0Ozxicj4NCisjaW5jbHVkZSAm bHQ7cnRlX21idWYuaCZndDs8YnI+DQorI2luY2x1ZGUgJmx0O3J0ZV9ldGhkZXYuaCZndDs8YnI+ DQorPGJyPg0KKyNpbmNsdWRlICZxdW90O2dyb190Y3A2LmgmcXVvdDs8YnI+DQorPGJyPg0KK3Zv aWQgKjxicj4NCitncm9fdGNwNl90YmxfY3JlYXRlKHVpbnQxNl90IHNvY2tldF9pZCw8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCBtYXhfZmxvd19udW0sPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgdWludDE2X3QgbWF4X2l0ZW1fcGVyX2Zsb3cpPGJyPg0KK3s8YnI+ DQorwqAgwqAgwqAgwqBzdHJ1Y3QgZ3JvX3RjcDZfdGJsICp0Ymw7PGJyPg0KK8KgIMKgIMKgIMKg c2l6ZV90IHNpemU7PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgZW50cmllc19udW0sIGk7PGJy Pg0KKzxicj4NCivCoCDCoCDCoCDCoGVudHJpZXNfbnVtID0gbWF4X2Zsb3dfbnVtICogbWF4X2l0 ZW1fcGVyX2Zsb3c7PGJyPg0KK8KgIMKgIMKgIMKgZW50cmllc19udW0gPSBSVEVfTUlOKGVudHJp ZXNfbnVtLCBHUk9fVENQNl9UQkxfTUFYX0lURU1fTlVNKTs8YnI+DQorPGJyPg0KK8KgIMKgIMKg IMKgaWYgKGVudHJpZXNfbnVtID09IDApPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0 dXJuIE5VTEw7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoHRibCA9IHJ0ZV96bWFsbG9jX3NvY2tl dChfX2Z1bmNfXyw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzaXpl b2Yoc3RydWN0IGdyb190Y3A2X3RibCksPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgUlRFX0NBQ0hFX0xJTkVfU0laRSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqBzb2NrZXRfaWQpOzxicj4NCivCoCDCoCDCoCDCoGlmICh0YmwgPT0gTlVM TCk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gTlVMTDs8YnI+DQorPGJyPg0K K8KgIMKgIMKgIMKgc2l6ZSA9IHNpemVvZihzdHJ1Y3QgZ3JvX3RjcF9pdGVtKSAqIGVudHJpZXNf bnVtOzxicj4NCivCoCDCoCDCoCDCoHRibC0mZ3Q7aXRlbXMgPSBydGVfem1hbGxvY19zb2NrZXQo X19mdW5jX18sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc2l6ZSw8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBSVEVfQ0FDSEVfTElORV9T SVpFLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHNvY2tldF9pZCk7 PGJyPg0KK8KgIMKgIMKgIMKgaWYgKHRibC0mZ3Q7aXRlbXMgPT0gTlVMTCkgezxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHJ0ZV9mcmVlKHRibCk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgcmV0dXJuIE5VTEw7PGJyPg0KK8KgIMKgIMKgIMKgfTxicj4NCivCoCDCoCDCoCDCoHRi bC0mZ3Q7bWF4X2l0ZW1fbnVtID0gZW50cmllc19udW07PGJyPg0KKzxicj4NCivCoCDCoCDCoCDC oHNpemUgPSBzaXplb2Yoc3RydWN0IGdyb190Y3A2X2Zsb3cpICogZW50cmllc19udW07PGJyPg0K K8KgIMKgIMKgIMKgdGJsLSZndDtmbG93cyA9IHJ0ZV96bWFsbG9jX3NvY2tldChfX2Z1bmNfXyw8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzaXplLDxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoFJURV9DQUNIRV9MSU5FX1NJWkUsPGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc29ja2V0X2lkKTs8YnI+DQorwqAg wqAgwqAgwqBpZiAodGJsLSZndDtmbG93cyA9PSBOVUxMKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgcnRlX2ZyZWUodGJsLSZndDtpdGVtcyk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgcnRlX2ZyZWUodGJsKTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4g TlVMTDs8YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KK8KgIMKgIMKgIMKgLyogSU5WQUxJRF9BUlJB WV9JTkRFWCBpbmRpY2F0ZXMgYW4gZW1wdHkgZmxvdyAqLzxicj4NCivCoCDCoCDCoCDCoGZvciAo aSA9IDA7IGkgJmx0OyBlbnRyaWVzX251bTsgaSsrKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoHRibC0mZ3Q7Zmxvd3NbaV0uc3RhcnRfaW5kZXggPSBJTlZBTElEX0FSUkFZX0lOREVYOzxi cj4NCivCoCDCoCDCoCDCoHRibC0mZ3Q7bWF4X2Zsb3dfbnVtID0gZW50cmllc19udW07PGJyPg0K Kzxicj4NCivCoCDCoCDCoCDCoHJldHVybiB0Ymw7PGJyPg0KK308YnI+DQorPGJyPg0KK3ZvaWQ8 YnI+DQorZ3JvX3RjcDZfdGJsX2Rlc3Ryb3kodm9pZCAqdGJsKTxicj4NCit7PGJyPg0KK8KgIMKg IMKgIMKgc3RydWN0IGdyb190Y3A2X3RibCAqdGNwX3RibCA9IHRibDs8YnI+DQorPGJyPg0KK8Kg IMKgIMKgIMKgaWYgKHRjcF90YmwpIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBydGVf ZnJlZSh0Y3BfdGJsLSZndDtpdGVtcyk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcnRl X2ZyZWUodGNwX3RibC0mZ3Q7Zmxvd3MpOzxicj4NCivCoCDCoCDCoCDCoH08YnI+DQorwqAgwqAg wqAgwqBydGVfZnJlZSh0Y3BfdGJsKTs8YnI+DQorfTxicj4NCis8YnI+DQorc3RhdGljIGlubGlu ZSB1aW50MzJfdDxicj4NCitmaW5kX2FuX2VtcHR5X2Zsb3coc3RydWN0IGdyb190Y3A2X3RibCAq dGJsKTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgaTs8YnI+DQorwqAgwqAgwqAg wqB1aW50MzJfdCBtYXhfZmxvd19udW0gPSB0YmwtJmd0O21heF9mbG93X251bTs8YnI+DQorPGJy Pg0KK8KgIMKgIMKgIMKgZm9yIChpID0gMDsgaSAmbHQ7IG1heF9mbG93X251bTsgaSsrKTxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmICh0YmwtJmd0O2Zsb3dzW2ldLnN0YXJ0X2luZGV4 ID09IElOVkFMSURfQVJSQVlfSU5ERVgpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgcmV0dXJuIGk7PGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIElOVkFMSURfQVJSQVlf SU5ERVg7PGJyPg0KK308YnI+DQorPGJyPg0KK3N0YXRpYyBpbmxpbmUgdWludDMyX3Q8YnI+DQor aW5zZXJ0X25ld19mbG93KHN0cnVjdCBncm9fdGNwNl90YmwgKnRibCw8YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqBzdHJ1Y3QgdGNwNl9mbG93X2tleSAqc3JjLDxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHVpbnQzMl90IGl0ZW1faWR4KTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKg c3RydWN0IHRjcDZfZmxvd19rZXkgKmRzdDs8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBmbG93 X2lkeDs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgZmxvd19pZHggPSBmaW5kX2FuX2VtcHR5X2Zs b3codGJsKTs8YnI+DQorwqAgwqAgwqAgwqBpZiAodW5saWtlbHkoZmxvd19pZHggPT0gSU5WQUxJ RF9BUlJBWV9JTkRFWCkpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIElOVkFM SURfQVJSQVlfSU5ERVg7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGRzdCA9ICZhbXA7KHRibC0m Z3Q7Zmxvd3NbZmxvd19pZHhdLmtleSk7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoEFTU0lHTl9D T01NT05fVENQX0tFWSgoJmFtcDtzcmMtJmd0O2Ntbl9rZXkpLCAoJmFtcDtkc3QtJmd0O2Ntbl9r ZXkpKTs8YnI+DQorwqAgwqAgwqAgwqBtZW1jcHkoJmFtcDtkc3QtJmd0O3NyY19hZGRyWzBdLCAm YW1wO3NyYy0mZ3Q7c3JjX2FkZHJbMF0sIHNpemVvZihkc3QtJmd0O3NyY19hZGRyKSk7PGJyPg0K K8KgIMKgIMKgIMKgbWVtY3B5KCZhbXA7ZHN0LSZndDtkc3RfYWRkclswXSwgJmFtcDtzcmMtJmd0 O2RzdF9hZGRyWzBdLCBzaXplb2YoZHN0LSZndDtkc3RfYWRkcikpOzxicj4NCivCoCDCoCDCoCDC oGRzdC0mZ3Q7dnRjX2Zsb3cgPSBzcmMtJmd0O3Z0Y19mbG93Ozxicj4NCis8YnI+DQorwqAgwqAg wqAgwqB0YmwtJmd0O2Zsb3dzW2Zsb3dfaWR4XS5zdGFydF9pbmRleCA9IGl0ZW1faWR4Ozxicj4N CivCoCDCoCDCoCDCoHRibC0mZ3Q7Zmxvd19udW0rKzs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKg cmV0dXJuIGZsb3dfaWR4Ozxicj4NCit9PGJyPg0KKzxicj4NCisvKjxicj4NCisgKiB1cGRhdGUg dGhlIHBhY2tldCBsZW5ndGggZm9yIHRoZSBmbHVzaGVkIHBhY2tldC48YnI+DQorICovPGJyPg0K K3N0YXRpYyBpbmxpbmUgdm9pZDxicj4NCit1cGRhdGVfaGVhZGVyKHN0cnVjdCBncm9fdGNwX2l0 ZW0gKml0ZW0pPGJyPg0KK3s8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX2lwdjZfaGRyICpp cHY2X2hkcjs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX21idWYgKnBrdCA9IGl0ZW0tJmd0 O2ZpcnN0c2VnOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBpcHY2X2hkciA9IChzdHJ1Y3QgcnRl X2lwdjZfaGRyICopKHJ0ZV9wa3RtYnVmX210b2QocGt0LCBjaGFyICopICs8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3QtJmd0O2wyX2xlbik7PGJyPg0KK8KgIMKg IMKgIMKgaXB2Nl9oZHItJmd0O3BheWxvYWRfbGVuID0gcnRlX2NwdV90b19iZV8xNihwa3QtJmd0 O3BrdF9sZW4gLTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdC0m Z3Q7bDJfbGVuIC0gcGt0LSZndDtsM19sZW4pOzxicj4NCit9PGJyPg0KKzxicj4NCitpbnQzMl90 PGJyPg0KK2dyb190Y3A2X3JlYXNzZW1ibGUoc3RydWN0IHJ0ZV9tYnVmICpwa3QsPGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgc3RydWN0IGdyb190Y3A2X3RibCAqdGJsLDxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQ2NF90IHN0YXJ0X3RpbWUpPGJyPg0KK3s8YnI+DQorwqAg wqAgwqAgwqBzdHJ1Y3QgcnRlX2V0aGVyX2hkciAqZXRoX2hkcjs8YnI+DQorwqAgwqAgwqAgwqBz dHJ1Y3QgcnRlX2lwdjZfaGRyICppcHY2X2hkcjs8YnI+DQorwqAgwqAgwqAgwqBpbnQzMl90IHRj cF9kbDs8YnI+DQorwqAgwqAgwqAgwqB1aW50MTZfdCBpcF90bGVuOzxicj4NCivCoCDCoCDCoCDC oHN0cnVjdCB0Y3A2X2Zsb3dfa2V5IGtleTs8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBpLCBt YXhfZmxvd19udW0sIHJlbWFpbmluZ19mbG93X251bTs8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJf dCBzZW50X3NlcTs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX3RjcF9oZHIgKnRjcF9oZHI7 PGJyPg0KK8KgIMKgIMKgIMKgdWludDhfdCBmaW5kOzxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90 IGl0ZW1faWR4Ozxicj4NCivCoCDCoCDCoCDCoC8qPGJyPg0KK8KgIMKgIMKgIMKgICogRG9uJiMz OTt0IHByb2Nlc3MgdGhlIHBhY2tldCB3aG9zZSBUQ1AgaGVhZGVyIGxlbmd0aCBpcyBncmVhdGVy PGJyPg0KK8KgIMKgIMKgIMKgICogdGhhbiA2MCBieXRlcyBvciBsZXNzIHRoYW4gMjAgYnl0ZXMu PGJyPg0KK8KgIMKgIMKgIMKgICovPGJyPg0KK8KgIMKgIMKgIMKgaWYgKHVubGlrZWx5KElOVkFM SURfVENQX0hEUkxFTihwa3QtJmd0O2w0X2xlbikpKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoHJldHVybiAtMTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgZXRoX2hkciA9IHJ0ZV9wa3Rt YnVmX210b2QocGt0LCBzdHJ1Y3QgcnRlX2V0aGVyX2hkciAqKTs8YnI+DQorwqAgwqAgwqAgwqBp cHY2X2hkciA9IChzdHJ1Y3QgcnRlX2lwdjZfaGRyICopKChjaGFyICopZXRoX2hkciArIHBrdC0m Z3Q7bDJfbGVuKTs8YnI+DQorwqAgwqAgwqAgwqB0Y3BfaGRyID0gcnRlX3BrdG1idWZfbXRvZF9v ZmZzZXQocGt0LCBzdHJ1Y3QgcnRlX3RjcF9oZHIgKiwgcGt0LSZndDtsMl9sZW4gKyBwa3QtJmd0 O2wzX2xlbik7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoC8qPGJyPg0KK8KgIMKgIMKgIMKgICog RG9uJiMzOTt0IHByb2Nlc3MgdGhlIHBhY2tldCB3aGljaCBoYXMgRklOLCBTWU4sIFJTVCwgUFNI LCBVUkcsIEVDRTxicj4NCivCoCDCoCDCoCDCoCAqIG9yIENXUiBzZXQuPGJyPg0KK8KgIMKgIMKg IMKgICovPGJyPg0KK8KgIMKgIMKgIMKgaWYgKHRjcF9oZHItJmd0O3RjcF9mbGFncyAhPSBSVEVf VENQX0FDS19GTEFHKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiAtMTs8YnI+ DQorPGJyPg0KK8KgIMKgIMKgIMKgaXBfdGxlbiA9IHJ0ZV9iZV90b19jcHVfMTYoaXB2Nl9oZHIt Jmd0O3BheWxvYWRfbGVuKTs8YnI+DQorwqAgwqAgwqAgwqAvKjxicj4NCivCoCDCoCDCoCDCoCAq IERvbiYjMzk7dCBwcm9jZXNzIHRoZSBwYWNrZXQgd2hvc2UgcGF5bG9hZCBsZW5ndGggaXMgbGVz cyB0aGFuIG9yPGJyPg0KK8KgIMKgIMKgIMKgICogZXF1YWwgdG8gMC48YnI+DQorwqAgwqAgwqAg wqAgKi88YnI+DQorwqAgwqAgwqAgwqB0Y3BfZGwgPSBpcF90bGVuIC0gcGt0LSZndDtsNF9sZW47 PGJyPg0KK8KgIMKgIMKgIMKgaWYgKHRjcF9kbCAmbHQ7PSAwKTxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoHJldHVybiAtMTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgcnRlX2V0aGVyX2Fk ZHJfY29weSgmYW1wOyhldGhfaGRyLSZndDtzcmNfYWRkciksICZhbXA7KGtleS5jbW5fa2V5LmV0 aF9zYWRkcikpOzxicj4NCivCoCDCoCDCoCDCoHJ0ZV9ldGhlcl9hZGRyX2NvcHkoJmFtcDsoZXRo X2hkci0mZ3Q7ZHN0X2FkZHIpLCAmYW1wOyhrZXkuY21uX2tleS5ldGhfZGFkZHIpKTs8YnI+DQor wqAgwqAgwqAgwqBtZW1jcHkoJmFtcDtrZXkuc3JjX2FkZHJbMF0sICZhbXA7aXB2Nl9oZHItJmd0 O3NyY19hZGRyLCBzaXplb2Yoa2V5LnNyY19hZGRyKSk7PGJyPg0KK8KgIMKgIMKgIMKgbWVtY3B5 KCZhbXA7a2V5LmRzdF9hZGRyWzBdLCAmYW1wO2lwdjZfaGRyLSZndDtkc3RfYWRkciwgc2l6ZW9m KGtleS5kc3RfYWRkcikpOzxicj4NCivCoCDCoCDCoCDCoGtleS5jbW5fa2V5LnNyY19wb3J0ID0g dGNwX2hkci0mZ3Q7c3JjX3BvcnQ7PGJyPg0KK8KgIMKgIMKgIMKga2V5LmNtbl9rZXkuZHN0X3Bv cnQgPSB0Y3BfaGRyLSZndDtkc3RfcG9ydDs8YnI+DQorwqAgwqAgwqAgwqBrZXkuY21uX2tleS5y ZWN2X2FjayA9IHRjcF9oZHItJmd0O3JlY3ZfYWNrOzxicj4NCivCoCDCoCDCoCDCoGtleS52dGNf ZmxvdyA9IGlwdjZfaGRyLSZndDt2dGNfZmxvdzs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgLyog U2VhcmNoIGZvciBhIG1hdGNoZWQgZmxvdy4gKi88YnI+DQorwqAgwqAgwqAgwqBtYXhfZmxvd19u dW0gPSB0YmwtJmd0O21heF9mbG93X251bTs8YnI+DQorwqAgwqAgwqAgwqByZW1haW5pbmdfZmxv d19udW0gPSB0YmwtJmd0O2Zsb3dfbnVtOzxicj4NCivCoCDCoCDCoCDCoGZpbmQgPSAwOzxicj4N CivCoCDCoCDCoCDCoGZvciAoaSA9IDA7IGkgJmx0OyBtYXhfZmxvd19udW0gJmFtcDsmYW1wOyBy ZW1haW5pbmdfZmxvd19udW07IGkrKykgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlm ICh0YmwtJmd0O2Zsb3dzW2ldLnN0YXJ0X2luZGV4ICE9IElOVkFMSURfQVJSQVlfSU5ERVgpIHs8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoaXNfc2FtZV90Y3A2 X2Zsb3coJmFtcDt0YmwtJmd0O2Zsb3dzW2ldLmtleSwgJmFtcDtrZXkpKSB7PGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZmluZCA9IDE7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgYnJlYWs7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfTxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJlbWFpbmluZ19mbG93X251bS0tOzxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KKzxicj4NCivCoCDC oCDCoCDCoGlmIChmaW5kID09IDApIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzZW50 X3NlcSA9IHJ0ZV9iZV90b19jcHVfMzIodGNwX2hkci0mZ3Q7c2VudF9zZXEpOzxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW1faWR4ID0gaW5zZXJ0X25ld190Y3BfaXRlbShwa3QsIHRi bC0mZ3Q7aXRlbXMsICZhbXA7dGJsLSZndDtpdGVtX251bSw8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0 YmwtJmd0O21heF9pdGVtX251bSwgc3RhcnRfdGltZSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBJTlZB TElEX0FSUkFZX0lOREVYLCBzZW50X3NlcSwgMCwgdHJ1ZSk7PGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgaWYgKGl0ZW1faWR4ID09IElOVkFMSURfQVJSQVlfSU5ERVgpPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIC0xOzxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoGlmIChpbnNlcnRfbmV3X2Zsb3codGJsLCAmYW1wO2tleSwgaXRlbV9pZHgp ID09PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgSU5WQUxJRF9BUlJB WV9JTkRFWCkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8qPGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICogRmFpbCB0byBpbnNlcnQg YSBuZXcgZmxvdywgc28gZGVsZXRlIHRoZTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCAqIHN0b3JlZCBwYWNrZXQuPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgICovPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg ZGVsZXRlX3RjcF9pdGVtKHRibC0mZ3Q7aXRlbXMsIGl0ZW1faWR4LCAmYW1wO3RibC0mZ3Q7aXRl bV9udW0sIElOVkFMSURfQVJSQVlfSU5ERVgpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHJldHVybiAtMTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIDA7PGJyPg0KK8KgIMKgIMKgIMKgfTxi cj4NCis8YnI+DQorwqAgwqAgwqAgwqByZXR1cm4gcHJvY2Vzc190Y3BfaXRlbShwa3QsIHRjcF9o ZHIsIHRjcF9kbCwgdGJsLSZndDtpdGVtcywgdGJsLSZndDtmbG93c1tpXS5zdGFydF9pbmRleCw8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAmYW1wO3RibC0mZ3Q7aXRlbV9udW0sIHRibC0mZ3Q7bWF4X2l0 ZW1fbnVtLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoDAsIHRydWUsIHN0YXJ0X3RpbWUpOzxicj4NCit9 PGJyPg0KKzxicj4NCit1aW50MTZfdDxicj4NCitncm9fdGNwNl90YmxfdGltZW91dF9mbHVzaChz dHJ1Y3QgZ3JvX3RjcDZfdGJsICp0YmwsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWlu dDY0X3QgZmx1c2hfdGltZXN0YW1wLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHN0cnVj dCBydGVfbWJ1ZiAqKm91dCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCBu Yl9vdXQpPGJyPg0KK3s8YnI+DQorwqAgwqAgwqAgwqB1aW50MTZfdCBrID0gMDs8YnI+DQorwqAg wqAgwqAgwqB1aW50MzJfdCBpLCBqOzxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IG1heF9mbG93 X251bSA9IHRibC0mZ3Q7bWF4X2Zsb3dfbnVtOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBmb3Ig KGkgPSAwOyBpICZsdDsgbWF4X2Zsb3dfbnVtOyBpKyspIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBpZiAodW5saWtlbHkodGJsLSZndDtmbG93X251bSA9PSAwKSk8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gazs8YnI+DQorPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgaiA9IHRibC0mZ3Q7Zmxvd3NbaV0uc3RhcnRfaW5kZXg7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgd2hpbGUgKGogIT0gSU5WQUxJRF9BUlJBWV9JTkRFWCkg ezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmICh0YmwtJmd0O2l0 ZW1zW2pdLnN0YXJ0X3RpbWUgJmx0Oz0gZmx1c2hfdGltZXN0YW1wKSB7PGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgb3V0W2srK10gPSB0YmwtJmd0 O2l0ZW1zW2pdLmZpcnN0c2VnOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoGlmICh0YmwtJmd0O2l0ZW1zW2pdLm5iX21lcmdlZCAmZ3Q7IDEpPGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgdXBkYXRlX2hlYWRlcigmYW1wOyh0YmwtJmd0O2l0ZW1zW2pdKSk7PGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyo8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKiBEZWxldGUgdGhlIHBh Y2tldCBhbmQgZ2V0IHRoZSBuZXh0PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgICogcGFja2V0IGluIHRoZSBmbG93Ljxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqLzxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGogPSBkZWxldGVfdGNwX2l0ZW0o dGJsLSZndDtpdGVtcywgaiw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAmYW1wO3RibC0mZ3Q7aXRlbV9u dW0sIElOVkFMSURfQVJSQVlfSU5ERVgpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRibC0mZ3Q7Zmxvd3NbaV0uc3RhcnRfaW5kZXggPSBqOzxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChq ID09IElOVkFMSURfQVJSQVlfSU5ERVgpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGJsLSZndDtmbG93X251bS0tOzxicj4N Cis8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBp ZiAodW5saWtlbHkoayA9PSBuYl9vdXQpKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBrOzxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH0gZWxzZTxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC8qPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICogVGhlIGxlZnQgcGFja2V0cyBpbiB0aGlz IGZsb3cgd29uJiMzOTt0IGJlPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgICogdGltZW91dC4gR28gdG8gY2hlY2sgb3RoZXIgZmxvd3MuPGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICovPGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgYnJlYWs7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgfTxicj4NCivCoCDCoCDCoCDCoH08YnI+DQorwqAg wqAgwqAgwqByZXR1cm4gazs8YnI+DQorfTxicj4NCis8YnI+DQordWludDMyX3Q8YnI+DQorZ3Jv X3RjcDZfdGJsX3BrdF9jb3VudCh2b2lkICp0YmwpPGJyPg0KK3s8YnI+DQorwqAgwqAgwqAgwqBz dHJ1Y3QgZ3JvX3RjcDZfdGJsICpncm9fdGJsID0gdGJsOzxicj4NCis8YnI+DQorwqAgwqAgwqAg wqBpZiAoZ3JvX3RibCk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4gZ3JvX3Ri bC0mZ3Q7aXRlbV9udW07PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoHJldHVybiAwOzxicj4NCit9 PGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vZ3JvX3RjcDYuaCBiL2xpYi9ncm8vZ3JvX3RjcDYu aDxicj4NCm5ldyBmaWxlIG1vZGUgMTAwNjQ0PGJyPg0KaW5kZXggMDAwMDAwMDAwMC4uY2MwMmIw MDA0YTxicj4NCi0tLSAvZGV2L251bGw8YnI+DQorKysgYi9saWIvZ3JvL2dyb190Y3A2Lmg8YnI+ DQpAQCAtMCwwICsxLDE2MSBAQDxicj4NCisvKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQlNE LTMtQ2xhdXNlPGJyPg0KKyAqIENvcHlyaWdodChjKSAyMDE3IEludGVsIENvcnBvcmF0aW9uPGJy Pg0KKyAqLzxicj4NCis8YnI+DQorI2lmbmRlZiBfR1JPX1RDUDZfSF88YnI+DQorI2RlZmluZSBf R1JPX1RDUDZfSF88YnI+DQorPGJyPg0KKyNpbmNsdWRlICZsdDtncm9fdGNwX2ludGVybmFsLmgm Z3Q7PGJyPg0KKzxicj4NCisjZGVmaW5lIElOVkFMSURfQVJSQVlfSU5ERVggMHhmZmZmZmZmZlVM PGJyPg0KKyNkZWZpbmUgR1JPX1RDUDZfVEJMX01BWF9JVEVNX05VTSAoMTAyNFVMICogMTAyNFVM KTxicj4NCis8YnI+DQorLyogSGVhZGVyIGZpZWxkcyByZXByZXNlbnRpbmcgYSBUQ1AvSVB2NiBm bG93ICovPGJyPg0KK3N0cnVjdCB0Y3A2X2Zsb3dfa2V5IHs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1 Y3QgY21uX3RjcF9rZXkgY21uX2tleTs8YnI+DQorwqAgwqAgwqAgwqB1aW50OF90wqAgc3JjX2Fk ZHJbMTZdOzxicj4NCivCoCDCoCDCoCDCoHVpbnQ4X3TCoCBkc3RfYWRkclsxNl07PGJyPg0KK8Kg IMKgIMKgIMKgcnRlX2JlMzJfdCB2dGNfZmxvdzs8YnI+DQorfTs8YnI+DQorPGJyPg0KK3N0cnVj dCBncm9fdGNwNl9mbG93IHs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgdGNwNl9mbG93X2tleSBr ZXk7PGJyPg0KK8KgIMKgIMKgIMKgLyo8YnI+DQorwqAgwqAgwqAgwqAgKiBUaGUgaW5kZXggb2Yg dGhlIGZpcnN0IHBhY2tldCBpbiB0aGUgZmxvdy48YnI+DQorwqAgwqAgwqAgwqAgKiBJTlZBTElE X0FSUkFZX0lOREVYIGluZGljYXRlcyBhbiBlbXB0eSBmbG93Ljxicj4NCivCoCDCoCDCoCDCoCAq Lzxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IHN0YXJ0X2luZGV4Ozxicj4NCit9Ozxicj4NCis8 YnI+DQorLyo8YnI+DQorICogVENQL0lQdjYgcmVhc3NlbWJseSB0YWJsZSBzdHJ1Y3R1cmUuPGJy Pg0KKyAqLzxicj4NCitzdHJ1Y3QgZ3JvX3RjcDZfdGJsIHs8YnI+DQorwqAgwqAgwqAgwqAvKiBp dGVtIGFycmF5ICovPGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IGdyb190Y3BfaXRlbSAqaXRlbXM7 PGJyPg0KK8KgIMKgIMKgIMKgLyogZmxvdyBhcnJheSAqLzxicj4NCivCoCDCoCDCoCDCoHN0cnVj dCBncm9fdGNwNl9mbG93ICpmbG93czs8YnI+DQorwqAgwqAgwqAgwqAvKiBjdXJyZW50IGl0ZW0g bnVtYmVyICovPGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgaXRlbV9udW07PGJyPg0KK8KgIMKg IMKgIMKgLyogY3VycmVudCBmbG93IG51bSAqLzxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IGZs b3dfbnVtOzxicj4NCivCoCDCoCDCoCDCoC8qIGl0ZW0gYXJyYXkgc2l6ZSAqLzxicj4NCivCoCDC oCDCoCDCoHVpbnQzMl90IG1heF9pdGVtX251bTs8YnI+DQorwqAgwqAgwqAgwqAvKiBmbG93IGFy cmF5IHNpemUgKi88YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBtYXhfZmxvd19udW07PGJyPg0K K307PGJyPg0KKzxicj4NCisvKio8YnI+DQorICogVGhpcyBmdW5jdGlvbiBjcmVhdGVzIGEgVENQ L0lQdjYgcmVhc3NlbWJseSB0YWJsZS48YnI+DQorICo8YnI+DQorICogQHBhcmFtIHNvY2tldF9p ZDxicj4NCisgKsKgIFNvY2tldCBpbmRleCBmb3IgYWxsb2NhdGluZyB0aGUgVENQL0lQdjYgcmVh c3NlbWJsZSB0YWJsZTxicj4NCisgKiBAcGFyYW0gbWF4X2Zsb3dfbnVtPGJyPg0KKyAqwqAgVGhl IG1heGltdW0gbnVtYmVyIG9mIGZsb3dzIGluIHRoZSBUQ1AvSVB2NiBHUk8gdGFibGU8YnI+DQor ICogQHBhcmFtIG1heF9pdGVtX3Blcl9mbG93PGJyPg0KKyAqwqAgVGhlIG1heGltdW0gbnVtYmVy IG9mIHBhY2tldHMgcGVyIGZsb3c8YnI+DQorICo8YnI+DQorICogQHJldHVybjxicj4NCisgKsKg IC0gUmV0dXJuIHRoZSB0YWJsZSBwb2ludGVyIG9uIHN1Y2Nlc3MuPGJyPg0KKyAqwqAgLSBSZXR1 cm4gTlVMTCBvbiBmYWlsdXJlLjxicj4NCisgKi88YnI+DQordm9pZCAqZ3JvX3RjcDZfdGJsX2Ny ZWF0ZSh1aW50MTZfdCBzb2NrZXRfaWQsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWlu dDE2X3QgbWF4X2Zsb3dfbnVtLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90 IG1heF9pdGVtX3Blcl9mbG93KTs8YnI+DQorPGJyPg0KKy8qKjxicj4NCisgKiBUaGlzIGZ1bmN0 aW9uIGRlc3Ryb3lzIGEgVENQL0lQdjYgcmVhc3NlbWJseSB0YWJsZS48YnI+DQorICo8YnI+DQor ICogQHBhcmFtIHRibDxicj4NCisgKsKgIFBvaW50ZXIgcG9pbnRpbmcgdG8gdGhlIFRDUC9JUHY2 IHJlYXNzZW1ibHkgdGFibGUuPGJyPg0KKyAqLzxicj4NCit2b2lkIGdyb190Y3A2X3RibF9kZXN0 cm95KHZvaWQgKnRibCk7PGJyPg0KKzxicj4NCisvKio8YnI+DQorICogVGhpcyBmdW5jdGlvbiBt ZXJnZXMgYSBUQ1AvSVB2NiBwYWNrZXQuIEl0IGRvZXNuJiMzOTt0IHByb2Nlc3MgdGhlIHBhY2tl dCw8YnI+DQorICogd2hpY2ggaGFzIFNZTiwgRklOLCBSU1QsIFBTSCwgQ1dSLCBFQ0Ugb3IgVVJH IHNldCwgb3IgZG9lc24mIzM5O3QgaGF2ZTxicj4NCisgKiBwYXlsb2FkLjxicj4NCisgKjxicj4N CisgKiBUaGlzIGZ1bmN0aW9uIGRvZXNuJiMzOTt0IGNoZWNrIGlmIHRoZSBwYWNrZXQgaGFzIGNv cnJlY3QgY2hlY2tzdW1zIGFuZDxicj4NCisgKiBkb2VzbiYjMzk7dCByZS1jYWxjdWxhdGUgY2hl Y2tzdW1zIGZvciB0aGUgbWVyZ2VkIHBhY2tldC4gQWRkaXRpb25hbGx5LDxicj4NCisgKiBpdCBh c3N1bWVzIHRoZSBwYWNrZXRzIGFyZSBjb21wbGV0ZSAoaS5lLiwgTUY9PTAgJmFtcDsmYW1wOyBm cmFnX29mZj09MCksPGJyPg0KKyAqIHdoZW4gSVAgZnJhZ21lbnRhdGlvbiBpcyBwb3NzaWJsZSAo aS5lLiwgREY9PTApLiBJdCByZXR1cm5zIHRoZTxicj4NCisgKiBwYWNrZXQsIGlmIHRoZSBwYWNr ZXQgaGFzIGludmFsaWQgcGFyYW1ldGVycyAoZS5nLiBTWU4gYml0IGlzIHNldCk8YnI+DQorICog b3IgdGhlcmUgaXMgbm8gYXZhaWxhYmxlIHNwYWNlIGluIHRoZSB0YWJsZS48YnI+DQorICo8YnI+ DQorICogQHBhcmFtIHBrdDxicj4NCisgKsKgIFBhY2tldCB0byByZWFzc2VtYmxlPGJyPg0KKyAq IEBwYXJhbSB0Ymw8YnI+DQorICrCoCBQb2ludGVyIHBvaW50aW5nIHRvIHRoZSBUQ1AvSVB2NiBy ZWFzc2VtYmx5IHRhYmxlPGJyPg0KKyAqIEBzdGFydF90aW1lPGJyPg0KKyAqwqAgVGhlIHRpbWUg d2hlbiB0aGUgcGFja2V0IGlzIGluc2VydGVkIGludG8gdGhlIHRhYmxlPGJyPg0KKyAqPGJyPg0K KyAqIEByZXR1cm48YnI+DQorICrCoCAtIFJldHVybiBhIHBvc2l0aXZlIHZhbHVlIGlmIHRoZSBw YWNrZXQgaXMgbWVyZ2VkLjxicj4NCisgKsKgIC0gUmV0dXJuIHplcm8gaWYgdGhlIHBhY2tldCBp c24mIzM5O3QgbWVyZ2VkIGJ1dCBzdG9yZWQgaW4gdGhlIHRhYmxlLjxicj4NCisgKsKgIC0gUmV0 dXJuIGEgbmVnYXRpdmUgdmFsdWUgZm9yIGludmFsaWQgcGFyYW1ldGVycyBvciBubyBhdmFpbGFi bGU8YnI+DQorICrCoCDCoCBzcGFjZSBpbiB0aGUgdGFibGUuPGJyPg0KKyAqLzxicj4NCitpbnQz Ml90IGdyb190Y3A2X3JlYXNzZW1ibGUoc3RydWN0IHJ0ZV9tYnVmICpwa3QsPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgc3RydWN0IGdyb190Y3A2X3RibCAqdGJsLDxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoHVpbnQ2NF90IHN0YXJ0X3RpbWUpOzxicj4NCis8YnI+DQorLyoqPGJy Pg0KKyAqIFRoaXMgZnVuY3Rpb24gZmx1c2hlcyB0aW1lb3V0IHBhY2tldHMgaW4gYSBUQ1AvSVB2 NiByZWFzc2VtYmx5IHRhYmxlLDxicj4NCisgKiBhbmQgd2l0aG91dCB1cGRhdGluZyBjaGVja3N1 bXMuPGJyPg0KKyAqPGJyPg0KKyAqIEBwYXJhbSB0Ymw8YnI+DQorICrCoCBUQ1AvSVB2NiByZWFz c2VtYmx5IHRhYmxlIHBvaW50ZXI8YnI+DQorICogQHBhcmFtIGZsdXNoX3RpbWVzdGFtcDxicj4N CisgKsKgIEZsdXNoIHBhY2tldHMgd2hpY2ggYXJlIGluc2VydGVkIGludG8gdGhlIHRhYmxlIGJl Zm9yZSBvciBhdCB0aGU8YnI+DQorICrCoCBmbHVzaF90aW1lc3RhbXAuPGJyPg0KKyAqIEBwYXJh bSBvdXQ8YnI+DQorICrCoCBQb2ludGVyIGFycmF5IHVzZWQgdG8ga2VlcCBmbHVzaGVkIHBhY2tl dHM8YnI+DQorICogQHBhcmFtIG5iX291dDxicj4NCisgKsKgIFRoZSBlbGVtZW50IG51bWJlciBp biAmIzM5O291dCYjMzk7LiBJdCBhbHNvIGRldGVybWluZXMgdGhlIG1heGltdW0gbnVtYmVyIG9m PGJyPg0KKyAqwqAgcGFja2V0cyB0aGF0IGNhbiBiZSBmbHVzaGVkIGZpbmFsbHkuPGJyPg0KKyAq PGJyPg0KKyAqIEByZXR1cm48YnI+DQorICrCoCBUaGUgbnVtYmVyIG9mIGZsdXNoZWQgcGFja2V0 czxicj4NCisgKi88YnI+DQordWludDE2X3QgZ3JvX3RjcDZfdGJsX3RpbWVvdXRfZmx1c2goc3Ry dWN0IGdyb190Y3A2X3RibCAqdGJsLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQ2 NF90IGZsdXNoX3RpbWVzdGFtcCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzdHJ1Y3Qg cnRlX21idWYgKipvdXQsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDE2X3QgbmJf b3V0KTs8YnI+DQorPGJyPg0KKy8qKjxicj4NCisgKiBUaGlzIGZ1bmN0aW9uIHJldHVybnMgdGhl IG51bWJlciBvZiB0aGUgcGFja2V0cyBpbiBhIFRDUC9JUHY2PGJyPg0KKyAqIHJlYXNzZW1ibHkg dGFibGUuPGJyPg0KKyAqPGJyPg0KKyAqIEBwYXJhbSB0Ymw8YnI+DQorICrCoCBUQ1AvSVB2NiBy ZWFzc2VtYmx5IHRhYmxlIHBvaW50ZXI8YnI+DQorICo8YnI+DQorICogQHJldHVybjxicj4NCisg KsKgIFRoZSBudW1iZXIgb2YgcGFja2V0cyBpbiB0aGUgdGFibGU8YnI+DQorICovPGJyPg0KK3Vp bnQzMl90IGdyb190Y3A2X3RibF9wa3RfY291bnQodm9pZCAqdGJsKTs8YnI+DQorPGJyPg0KKy8q PGJyPg0KKyAqIENoZWNrIGlmIHR3byBUQ1AvSVB2NiBwYWNrZXRzIGJlbG9uZyB0byB0aGUgc2Ft ZSBmbG93Ljxicj4NCisgKi88YnI+DQorc3RhdGljIGlubGluZSBpbnQ8YnI+DQoraXNfc2FtZV90 Y3A2X2Zsb3coc3RydWN0IHRjcDZfZmxvd19rZXkgKmsxLCBzdHJ1Y3QgdGNwNl9mbG93X2tleSAq azIpPGJyPg0KK3s8YnI+DQorwqAgwqAgwqAgwqBydGVfYmUzMl90IHZ0Y19mbG93X2RpZmY7PGJy Pg0KKzxicj4NCivCoCDCoCDCoCDCoGlmIChtZW1jbXAoJmFtcDtrMS0mZ3Q7c3JjX2FkZHIsICZh bXA7azItJmd0O3NyY19hZGRyLCAxNikpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0 dXJuIDA7PGJyPg0KK8KgIMKgIMKgIMKgaWYgKG1lbWNtcCgmYW1wO2sxLSZndDtkc3RfYWRkciwg JmFtcDtrMi0mZ3Q7ZHN0X2FkZHIsIDE2KSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBy ZXR1cm4gMDs8YnI+DQorwqAgwqAgwqAgwqAvKjxicj4NCivCoCDCoCDCoCDCoCAqIElQIHZlcnNp b24gKDQpIFRyYWZmaWMgQ2xhc3MgKDgpIEZsb3cgTGFiZWwgKDIwKTxicj4NCivCoCDCoCDCoCDC oCAqIEFsbCBmaWVsZHMgZXhjZXB0IFRyYWZmaWMgY2xhc3Mgc2hvdWxkIGJlIHNhbWU8YnI+DQor wqAgwqAgwqAgwqAgKi88YnI+DQorwqAgwqAgwqAgwqB2dGNfZmxvd19kaWZmID0gKGsxLSZndDt2 dGNfZmxvdyBeIGsyLSZndDt2dGNfZmxvdyk7PGJyPg0KK8KgIMKgIMKgIMKgaWYgKHZ0Y19mbG93 X2RpZmYgJmFtcDsgaHRvbmwoMHhGMDBGRkZGRikpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgcmV0dXJuIDA7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoHJldHVybiBpc19jb21tb25fdGNw X2tleSgmYW1wO2sxLSZndDtjbW5fa2V5LCAmYW1wO2syLSZndDtjbW5fa2V5KTs8YnI+DQorfTxi cj4NCis8YnI+DQorI2VuZGlmPGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vZ3JvX3RjcF9pbnRl cm5hbC5jIGIvbGliL2dyby9ncm9fdGNwX2ludGVybmFsLmM8YnI+DQpuZXcgZmlsZSBtb2RlIDEw MDY0NDxicj4NCmluZGV4IDAwMDAwMDAwMDAuLjVhMjFiY2E3Zjg8YnI+DQotLS0gL2Rldi9udWxs PGJyPg0KKysrIGIvbGliL2dyby9ncm9fdGNwX2ludGVybmFsLmM8YnI+DQpAQCAtMCwwICsxLDEy OCBAQDxicj4NCisvKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQlNELTMtQ2xhdXNlPGJyPg0K KyAqIENvcHlyaWdodChjKSAyMDE3IEludGVsIENvcnBvcmF0aW9uPGJyPg0KKyAqLzxicj4NCisj aW5jbHVkZSAmbHQ7cnRlX21hbGxvYy5oJmd0Ozxicj4NCisjaW5jbHVkZSAmbHQ7cnRlX21idWYu aCZndDs8YnI+DQorI2luY2x1ZGUgJmx0O3J0ZV9ldGhkZXYuaCZndDs8YnI+DQorPGJyPg0KKyNp bmNsdWRlICZxdW90O2dyb190Y3BfaW50ZXJuYWwuaCZxdW90Ozxicj4NCis8YnI+DQorc3RhdGlj IGlubGluZSB1aW50MzJfdDxicj4NCitmaW5kX2FuX2VtcHR5X2l0ZW0oc3RydWN0IGdyb190Y3Bf aXRlbSAqaXRlbXMsPGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgbWF4X2l0ZW1fbnVtKTxicj4N Cit7PGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgaTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKg Zm9yIChpID0gMDsgaSAmbHQ7IG1heF9pdGVtX251bTsgaSsrKTxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoGlmIChpdGVtc1tpXS5maXJzdHNlZyA9PSBOVUxMKTxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiBpOzxicj4NCivCoCDCoCDCoCDCoHJldHVy biBJTlZBTElEX0FSUkFZX0lOREVYOzxicj4NCit9PGJyPg0KKzxicj4NCitpbmxpbmUgdWludDMy X3Q8YnI+DQoraW5zZXJ0X25ld190Y3BfaXRlbShzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzdHJ1Y3QgZ3JvX3RjcF9pdGVtICppdGVtcyw8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MzJfdCAqaXRlbV9udW0sPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgdWludDMyX3QgbWF4X2l0ZW1fbnVtLDxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoHVpbnQ2NF90IHN0YXJ0X3RpbWUsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgdWludDMyX3QgcHJldl9pZHgsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDMy X3Qgc2VudF9zZXEsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDE2X3QgaXBfaWQs PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDhfdCBpc19hdG9taWMpPGJyPg0KK3s8 YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBpdGVtX2lkeDs8YnI+DQorPGJyPg0KK8KgIMKgIMKg IMKgaXRlbV9pZHggPSBmaW5kX2FuX2VtcHR5X2l0ZW0oaXRlbXMsIG1heF9pdGVtX251bSk7PGJy Pg0KK8KgIMKgIMKgIMKgaWYgKGl0ZW1faWR4ID09IElOVkFMSURfQVJSQVlfSU5ERVgpPGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIElOVkFMSURfQVJSQVlfSU5ERVg7PGJyPg0K Kzxicj4NCivCoCDCoCDCoCDCoGl0ZW1zW2l0ZW1faWR4XS5maXJzdHNlZyA9IHBrdDs8YnI+DQor wqAgwqAgwqAgwqBpdGVtc1tpdGVtX2lkeF0ubGFzdHNlZyA9IHJ0ZV9wa3RtYnVmX2xhc3RzZWco cGt0KTs8YnI+DQorwqAgwqAgwqAgwqBpdGVtc1tpdGVtX2lkeF0uc3RhcnRfdGltZSA9IHN0YXJ0 X3RpbWU7PGJyPg0KK8KgIMKgIMKgIMKgaXRlbXNbaXRlbV9pZHhdLm5leHRfcGt0X2lkeCA9IElO VkFMSURfQVJSQVlfSU5ERVg7PGJyPg0KK8KgIMKgIMKgIMKgaXRlbXNbaXRlbV9pZHhdLnNlbnRf c2VxID0gc2VudF9zZXE7PGJyPg0KK8KgIMKgIMKgIMKgaXRlbXNbaXRlbV9pZHhdLmwzLmlwX2lk ID0gaXBfaWQ7PGJyPg0KK8KgIMKgIMKgIMKgaXRlbXNbaXRlbV9pZHhdLm5iX21lcmdlZCA9IDE7 PGJyPg0KK8KgIMKgIMKgIMKgaXRlbXNbaXRlbV9pZHhdLmlzX2F0b21pYyA9IGlzX2F0b21pYzs8 YnI+DQorwqAgwqAgwqAgwqAoKml0ZW1fbnVtKSArPSAxOzxicj4NCis8YnI+DQorwqAgwqAgwqAg wqAvKiBpZiB0aGUgcHJldmlvdXMgcGFja2V0IGV4aXN0cywgY2hhaW4gdGhlbSB0b2dldGhlci4g Ki88YnI+DQorwqAgwqAgwqAgwqBpZiAocHJldl9pZHggIT0gSU5WQUxJRF9BUlJBWV9JTkRFWCkg ezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW1zW2l0ZW1faWR4XS5uZXh0X3BrdF9p ZHggPTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW1zW3ByZXZf aWR4XS5uZXh0X3BrdF9pZHg7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaXRlbXNbcHJl dl9pZHhdLm5leHRfcGt0X2lkeCA9IGl0ZW1faWR4Ozxicj4NCivCoCDCoCDCoCDCoH08YnI+DQor PGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIGl0ZW1faWR4Ozxicj4NCit9PGJyPg0KKzxicj4NCitp bmxpbmUgdWludDMyX3Q8YnI+DQorZGVsZXRlX3RjcF9pdGVtKHN0cnVjdCBncm9fdGNwX2l0ZW0g Kml0ZW1zLCB1aW50MzJfdCBpdGVtX2lkeCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1 aW50MzJfdCAqaXRlbV9udW0sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDMyX3Qg cHJldl9pdGVtX2lkeCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IG5leHRfaWR4 ID0gaXRlbXNbaXRlbV9pZHhdLm5leHRfcGt0X2lkeDs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKg LyogTlVMTCBpbmRpY2F0ZXMgYW4gZW1wdHkgaXRlbSAqLzxicj4NCivCoCDCoCDCoCDCoGl0ZW1z W2l0ZW1faWR4XS5maXJzdHNlZyA9IE5VTEw7PGJyPg0KK8KgIMKgIMKgIMKgKCppdGVtX251bSkg LT0gMTs8YnI+DQorwqAgwqAgwqAgwqBpZiAocHJldl9pdGVtX2lkeCAhPSBJTlZBTElEX0FSUkFZ X0lOREVYKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW1zW3ByZXZfaXRlbV9pZHhd Lm5leHRfcGt0X2lkeCA9IG5leHRfaWR4Ozxicj4NCis8YnI+DQorwqAgwqAgwqAgwqByZXR1cm4g bmV4dF9pZHg7PGJyPg0KK308YnI+DQorPGJyPg0KK2ludDMyX3Q8YnI+DQorcHJvY2Vzc190Y3Bf aXRlbShzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX3Rj cF9oZHIgKnRjcF9oZHIsPGJyPg0KK8KgIMKgIMKgIMKgaW50MzJfdCB0Y3BfZGwsPGJyPg0KK8Kg IMKgIMKgIMKgc3RydWN0IGdyb190Y3BfaXRlbSAqaXRlbXMsPGJyPg0KK8KgIMKgIMKgIMKgdWlu dDMyX3QgaXRlbV9pZHgsPGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgKml0ZW1fbnVtLDxicj4N CivCoCDCoCDCoCDCoHVpbnQzMl90IG1heF9pdGVtX251bSw8YnI+DQorwqAgwqAgwqAgwqB1aW50 MTZfdCBpcF9pZCw8YnI+DQorwqAgwqAgwqAgwqB1aW50OF90IGlzX2F0b21pYyw8YnI+DQorwqAg wqAgwqAgwqB1aW50NjRfdCBzdGFydF90aW1lKTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKgdWlu dDMyX3QgY3VyX2lkeDs8YnI+DQorwqAgwqAgwqAgwqB1aW50MzJfdCBwcmV2X2lkeDs8YnI+DQor wqAgwqAgwqAgwqBpbnQgY21wOzxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRfc2VxOzxi cj4NCis8YnI+DQorwqAgwqAgwqAgwqBzZW50X3NlcSA9IHJ0ZV9iZV90b19jcHVfMzIodGNwX2hk ci0mZ3Q7c2VudF9zZXEpOzxicj4NCivCoCDCoCDCoCDCoC8qPGJyPg0KK8KgIMKgIMKgIMKgICog Q2hlY2sgYWxsIHBhY2tldHMgaW4gdGhlIGZsb3cgYW5kIHRyeSB0byBmaW5kIGEgbmVpZ2hib3Ig Zm9yPGJyPg0KK8KgIMKgIMKgIMKgICogdGhlIGlucHV0IHBhY2tldC48YnI+DQorwqAgwqAgwqAg wqAgKi88YnI+DQorwqAgwqAgwqAgwqBjdXJfaWR4ID0gaXRlbV9pZHg7PGJyPg0KK8KgIMKgIMKg IMKgcHJldl9pZHggPSBjdXJfaWR4Ozxicj4NCivCoCDCoCDCoCDCoGRvIHs8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBjbXAgPSBjaGVja19zZXFfb3B0aW9uKCZhbXA7aXRlbXNbY3VyX2lk eF0sIHRjcF9oZHIsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgc2VudF9zZXEsIGlwX2lkLCBwa3QtJmd0O2w0X2xlbiwgdGNwX2RsLCAwLDxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlzX2F0b21p Yyk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGNtcCkgezxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChtZXJnZV90d29fdGNwX3BhY2tldHMoJmFt cDtpdGVtc1tjdXJfaWR4XSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwa3QsIGNtcCwgc2VudF9zZXEs IGlwX2lkLCAwKSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqByZXR1cm4gMTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAvKjxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqIEZhaWwgdG8g bWVyZ2UgdGhlIHR3byBwYWNrZXRzLCBhcyB0aGUgcGFja2V0PGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgICogbGVuZ3RoIGlzIGdyZWF0ZXIgdGhhbiB0aGUgbWF4IHZh bHVlLiBTdG9yZTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAqIHRo ZSBwYWNrZXQgaW50byB0aGUgZmxvdy48YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAo aW5zZXJ0X25ld190Y3BfaXRlbShwa3QsIGl0ZW1zLCBpdGVtX251bSwgbWF4X2l0ZW1fbnVtLDxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHN0YXJ0X3RpbWUsIGN1cl9pZHgsIHNlbnRfc2VxLCBpcF9pZCwg aXNfYXRvbWljKSA9PTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoElOVkFMSURfQVJSQVlfSU5ERVgpPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0dXJuIC0xOzxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiAwOzxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwcmV2X2lkeCA9 IGN1cl9pZHg7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgY3VyX2lkeCA9IGl0ZW1zW2N1 cl9pZHhdLm5leHRfcGt0X2lkeDs8YnI+DQorwqAgwqAgwqAgwqB9IHdoaWxlIChjdXJfaWR4ICE9 IElOVkFMSURfQVJSQVlfSU5ERVgpOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAvKiBGYWlsIHRv IGZpbmQgYSBuZWlnaGJvciwgc28gc3RvcmUgdGhlIHBhY2tldCBpbnRvIHRoZSBmbG93LiAqLzxi cj4NCivCoCDCoCDCoCDCoGlmIChpbnNlcnRfbmV3X3RjcF9pdGVtKHBrdCwgaXRlbXMsIGl0ZW1f bnVtLCBtYXhfaXRlbV9udW0sIHN0YXJ0X3RpbWUsIHByZXZfaWR4LCBzZW50X3NlcSw8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpcF9pZCwgaXNf YXRvbWljKSA9PSBJTlZBTElEX0FSUkFZX0lOREVYKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoHJldHVybiAtMTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIDA7PGJyPg0KK308 YnI+DQpkaWZmIC0tZ2l0IGEvbGliL2dyby9ncm9fdGNwX2ludGVybmFsLmggYi9saWIvZ3JvL2dy b190Y3BfaW50ZXJuYWwuaDxicj4NCm5ldyBmaWxlIG1vZGUgMTAwNjQ0PGJyPg0KaW5kZXggMDAw MDAwMDAwMC4uMDcyYjdhZWExMzxicj4NCi0tLSAvZGV2L251bGw8YnI+DQorKysgYi9saWIvZ3Jv L2dyb190Y3BfaW50ZXJuYWwuaDxicj4NCkBAIC0wLDAgKzEsMjEyIEBAPGJyPg0KKyNpZm5kZWYg X0dST19UQ1BfSF88YnI+DQorI2RlZmluZSBfR1JPX1RDUF9IXzxicj4NCis8YnI+DQorI2RlZmlu ZSBJTlZBTElEX0FSUkFZX0lOREVYIDB4ZmZmZmZmZmZVTDxicj4NCis8YnI+DQorI2luY2x1ZGUg Jmx0O3J0ZV90Y3AuaCZndDs8YnI+DQorPGJyPg0KKy8qPGJyPg0KKyAqIFRoZSBtYXggbGVuZ3Ro IG9mIGEgSVB2NCBwYWNrZXQsIHdoaWNoIGluY2x1ZGVzIHRoZSBsZW5ndGggb2YgdGhlIEwzPGJy Pg0KKyAqIGhlYWRlciwgdGhlIEw0IGhlYWRlciBhbmQgdGhlIGRhdGEgcGF5bG9hZC48YnI+DQor ICovPGJyPg0KKyNkZWZpbmUgTUFYX0lQX1BLVF9MRU5HVEggVUlOVDE2X01BWDxicj4NCis8YnI+ DQorLyogVGhlIG1heGltdW0gVENQIGhlYWRlciBsZW5ndGggKi88YnI+DQorI2RlZmluZSBNQVhf VENQX0hMRU4gNjA8YnI+DQorI2RlZmluZSBJTlZBTElEX1RDUF9IRFJMRU4obGVuKSBcPGJyPg0K K8KgIMKgIMKgIMKgKCgobGVuKSAmbHQ7IHNpemVvZihzdHJ1Y3QgcnRlX3RjcF9oZHIpKSB8fCAo KGxlbikgJmd0OyBNQVhfVENQX0hMRU4pKTxicj4NCis8YnI+DQorc3RydWN0IGNtbl90Y3Bfa2V5 IHs8YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX2V0aGVyX2FkZHIgZXRoX3NhZGRyOzxicj4N CivCoCDCoCDCoCDCoHN0cnVjdCBydGVfZXRoZXJfYWRkciBldGhfZGFkZHI7PGJyPg0KK8KgIMKg IMKgIMKgdWludDMyX3QgcmVjdl9hY2s7PGJyPg0KK8KgIMKgIMKgIMKgdWludDE2X3Qgc3JjX3Bv cnQ7PGJyPg0KK8KgIMKgIMKgIMKgdWludDE2X3QgZHN0X3BvcnQ7PGJyPg0KK307PGJyPg0KKzxi cj4NCisjZGVmaW5lIEFTU0lHTl9DT01NT05fVENQX0tFWShrMSwgazIpIFw8YnI+DQorwqAgwqAg wqAgwqBkbyB7XDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJ0ZV9ldGhlcl9hZGRyX2Nv cHkoJmFtcDsoazEtJmd0O2V0aF9zYWRkciksICZhbXA7KGsyLSZndDtldGhfc2FkZHIpKTsgXDxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJ0ZV9ldGhlcl9hZGRyX2NvcHkoJmFtcDsoazEt Jmd0O2V0aF9kYWRkciksICZhbXA7KGsyLSZndDtldGhfZGFkZHIpKTsgXDxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoGsyLSZndDtyZWN2X2FjayA9IGsxLSZndDtyZWN2X2FjazsgXDxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGsyLSZndDtzcmNfcG9ydCA9IGsxLSZndDtzcmNfcG9y dDsgXDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGsyLSZndDtkc3RfcG9ydCA9IGsxLSZn dDtkc3RfcG9ydDsgXDxicj4NCivCoCDCoCDCoCDCoH0gd2hpbGUgKDApPGJyPg0KKzxicj4NCitz dHJ1Y3QgZ3JvX3RjcF9pdGVtIHs8YnI+DQorwqAgwqAgwqAgwqAvKjxicj4NCivCoCDCoCDCoCDC oCAqIFRoZSBmaXJzdCBNQlVGIHNlZ21lbnQgb2YgdGhlIHBhY2tldC4gSWYgdGhlIHZhbHVlPGJy Pg0KK8KgIMKgIMKgIMKgICogaXMgTlVMTCwgaXQgbWVhbnMgdGhlIGl0ZW0gaXMgZW1wdHkuPGJy Pg0KK8KgIMKgIMKgIMKgICovPGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IHJ0ZV9tYnVmICpmaXJz dHNlZzs8YnI+DQorwqAgwqAgwqAgwqAvKiBUaGUgbGFzdCBNQlVGIHNlZ21lbnQgb2YgdGhlIHBh Y2tldCAqLzxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBydGVfbWJ1ZiAqbGFzdHNlZzs8YnI+DQor wqAgwqAgwqAgwqAvKjxicj4NCivCoCDCoCDCoCDCoCAqIFRoZSB0aW1lIHdoZW4gdGhlIGZpcnN0 IHBhY2tldCBpcyBpbnNlcnRlZCBpbnRvIHRoZSB0YWJsZS48YnI+DQorwqAgwqAgwqAgwqAgKiBU aGlzIHZhbHVlIHdvbiYjMzk7dCBiZSB1cGRhdGVkLCBldmVuIGlmIHRoZSBwYWNrZXQgaXMgbWVy Z2VkPGJyPg0KK8KgIMKgIMKgIMKgICogd2l0aCBvdGhlciBwYWNrZXRzLjxicj4NCivCoCDCoCDC oCDCoCAqLzxicj4NCivCoCDCoCDCoCDCoHVpbnQ2NF90IHN0YXJ0X3RpbWU7PGJyPg0KK8KgIMKg IMKgIMKgLyo8YnI+DQorwqAgwqAgwqAgwqAgKiBuZXh0X3BrdF9pZHggaXMgdXNlZCB0byBjaGFp biB0aGUgcGFja2V0cyB0aGF0PGJyPg0KK8KgIMKgIMKgIMKgICogYXJlIGluIHRoZSBzYW1lIGZs b3cgYnV0IGNhbiYjMzk7dCBiZSBtZXJnZWQgdG9nZXRoZXI8YnI+DQorwqAgwqAgwqAgwqAgKiAo ZS5nLiBjYXVzZWQgYnkgcGFja2V0IHJlb3JkZXJpbmcpLjxicj4NCivCoCDCoCDCoCDCoCAqLzxi cj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IG5leHRfcGt0X2lkeDs8YnI+DQorwqAgwqAgwqAgwqAv KiBUQ1Agc2VxdWVuY2UgbnVtYmVyIG9mIHRoZSBwYWNrZXQgKi88YnI+DQorwqAgwqAgwqAgwqB1 aW50MzJfdCBzZW50X3NlcTs8YnI+DQorwqAgwqAgwqAgwqB1bmlvbiB7PGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgLyogSVB2NCBJRCBvZiB0aGUgcGFja2V0ICovPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgdWludDE2X3QgaXBfaWQ7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgLyogVW51c2VkIGZpZWxkIGZvciBJUHY2ICovPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgdWludDE2X3QgdW51c2VkOzxicj4NCivCoCDCoCDCoCDCoH0gbDM7PGJyPg0KK8KgIMKgIMKg IMKgLyogdGhlIG51bWJlciBvZiBtZXJnZWQgcGFja2V0cyAqLzxicj4NCivCoCDCoCDCoCDCoHVp bnQxNl90IG5iX21lcmdlZDs8YnI+DQorwqAgwqAgwqAgwqAvKiBJbmRpY2F0ZSBpZiBJUHY0IElE IGNhbiBiZSBpZ25vcmVkICovPGJyPg0KK8KgIMKgIMKgIMKgdWludDhfdCBpc19hdG9taWM7PGJy Pg0KK307PGJyPg0KKzxicj4NCit1aW50MzJfdDxicj4NCitpbnNlcnRfbmV3X3RjcF9pdGVtKHN0 cnVjdCBydGVfbWJ1ZiAqcGt0LDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHN0cnVjdCBn cm9fdGNwX2l0ZW0gKml0ZW1zLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90 ICppdGVtX251bSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MzJfdCBtYXhfaXRl bV9udW0sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdWludDY0X3Qgc3RhcnRfdGltZSw8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MzJfdCBwcmV2X2lkeCw8YnI+DQorwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MzJfdCBzZW50X3NlcSw8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqB1aW50MTZfdCBpcF9pZCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1 aW50OF90IGlzX2F0b21pYyk7PGJyPg0KKzxicj4NCit1aW50MzJfdDxicj4NCitkZWxldGVfdGNw X2l0ZW0oc3RydWN0IGdyb190Y3BfaXRlbSAqaXRlbXMsIHVpbnQzMl90IGl0ZW1faWR4LDxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90ICppdGVtX251bSw8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqB1aW50MzJfdCBwcmV2X2l0ZW1faWR4KTs8YnI+DQorPGJyPg0KK2lu dDMyX3Q8YnI+DQorcHJvY2Vzc190Y3BfaXRlbShzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQor wqAgwqAgwqAgwqBzdHJ1Y3QgcnRlX3RjcF9oZHIgKnRjcF9oZHIsPGJyPg0KK8KgIMKgIMKgIMKg aW50MzJfdCB0Y3BfZGwsPGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IGdyb190Y3BfaXRlbSAqaXRl bXMsPGJyPg0KK8KgIMKgIMKgIMKgdWludDMyX3QgaXRlbV9pZHgsPGJyPg0KK8KgIMKgIMKgIMKg dWludDMyX3QgKml0ZW1fbnVtLDxicj4NCivCoCDCoCDCoCDCoHVpbnQzMl90IG1heF9pdGVtX251 bSw8YnI+DQorwqAgwqAgwqAgwqB1aW50MTZfdCBpcF9pZCw8YnI+DQorwqAgwqAgwqAgwqB1aW50 OF90IGlzX2F0b21pYyw8YnI+DQorwqAgwqAgwqAgwqB1aW50NjRfdCBzdGFydF90aW1lKTs8YnI+ DQorPGJyPg0KKy8qPGJyPg0KKyAqIE1lcmdlIHR3byBUQ1AgcGFja2V0cyB3aXRob3V0IHVwZGF0 aW5nIGNoZWNrc3Vtcy48YnI+DQorICogSWYgY21wIGlzIGxhcmdlciB0aGFuIDAsIGFwcGVuZCB0 aGUgbmV3IHBhY2tldCB0byB0aGU8YnI+DQorICogb3JpZ2luYWwgcGFja2V0LiBPdGhlcndpc2Us IHByZS1wZW5kIHRoZSBuZXcgcGFja2V0IHRvPGJyPg0KKyAqIHRoZSBvcmlnaW5hbCBwYWNrZXQu PGJyPg0KKyAqLzxicj4NCitzdGF0aWMgaW5saW5lIGludDxicj4NCittZXJnZV90d29fdGNwX3Bh Y2tldHMoc3RydWN0IGdyb190Y3BfaXRlbSAqaXRlbSw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBzdHJ1Y3QgcnRlX21idWYgKnBrdCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBp bnQgY21wLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQzMl90IHNlbnRfc2VxLDxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGlwX2lkLDxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGwyX29mZnNldCk8YnI+DQorezxicj4NCivCoCDCoCDC oCDCoHN0cnVjdCBydGVfbWJ1ZiAqcGt0X2hlYWQsICpwa3RfdGFpbCwgKmxhc3RzZWc7PGJyPg0K K8KgIMKgIMKgIMKgdWludDE2X3QgaGRyX2xlbiwgbDJfbGVuOzxicj4NCis8YnI+DQorwqAgwqAg wqAgwqBpZiAoY21wICZndDsgMCkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBrdF9o ZWFkID0gaXRlbS0mZ3Q7Zmlyc3RzZWc7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcGt0 X3RhaWwgPSBwa3Q7PGJyPg0KK8KgIMKgIMKgIMKgfSBlbHNlIHs8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBwa3RfaGVhZCA9IHBrdDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBw a3RfdGFpbCA9IGl0ZW0tJmd0O2ZpcnN0c2VnOzxicj4NCivCoCDCoCDCoCDCoH08YnI+DQorPGJy Pg0KK8KgIMKgIMKgIMKgLyogY2hlY2sgaWYgdGhlIElQdjQgcGFja2V0IGxlbmd0aCBpcyBncmVh dGVyIHRoYW4gdGhlIG1heCB2YWx1ZSAqLzxicj4NCivCoCDCoCDCoCDCoGhkcl9sZW4gPSBsMl9v ZmZzZXQgKyBwa3RfaGVhZC0mZ3Q7bDJfbGVuICsgcGt0X2hlYWQtJmd0O2wzX2xlbiArPGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcGt0X2hlYWQtJmd0O2w0X2xlbjs8YnI+DQorwqAgwqAg wqAgwqBsMl9sZW4gPSBsMl9vZmZzZXQgJmd0OyAwID8gcGt0X2hlYWQtJmd0O291dGVyX2wyX2xl biA6IHBrdF9oZWFkLSZndDtsMl9sZW47PGJyPg0KK8KgIMKgIMKgIMKgaWYgKHVubGlrZWx5KHBr dF9oZWFkLSZndDtwa3RfbGVuIC0gbDJfbGVuICsgcGt0X3RhaWwtJmd0O3BrdF9sZW4gLTxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGhkcl9sZW4g Jmd0OyBNQVhfSVBfUEtUX0xFTkdUSCkpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0 dXJuIDA7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoC8qIHJlbW92ZSB0aGUgcGFja2V0IGhlYWRl ciBmb3IgdGhlIHRhaWwgcGFja2V0ICovPGJyPg0KK8KgIMKgIMKgIMKgcnRlX3BrdG1idWZfYWRq KHBrdF90YWlsLCBoZHJfbGVuKTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgLyogY2hhaW4gdHdv IHBhY2tldHMgdG9nZXRoZXIgKi88YnI+DQorwqAgwqAgwqAgwqBpZiAoY21wICZndDsgMCkgezxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGl0ZW0tJmd0O2xhc3RzZWctJmd0O25leHQgPSBw a3Q7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaXRlbS0mZ3Q7bGFzdHNlZyA9IHJ0ZV9w a3RtYnVmX2xhc3RzZWcocGt0KTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiB1cGRh dGUgSVAgSUQgdG8gdGhlIGxhcmdlciB2YWx1ZSAqLzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoGl0ZW0tJmd0O2wzLmlwX2lkID0gaXBfaWQ7PGJyPg0KK8KgIMKgIMKgIMKgfSBlbHNlIHs8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBsYXN0c2VnID0gcnRlX3BrdG1idWZfbGFzdHNl Zyhwa3QpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGxhc3RzZWctJmd0O25leHQgPSBp dGVtLSZndDtmaXJzdHNlZzs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpdGVtLSZndDtm aXJzdHNlZyA9IHBrdDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiB1cGRhdGUgc2Vu dF9zZXEgdG8gdGhlIHNtYWxsZXIgdmFsdWUgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBpdGVtLSZndDtzZW50X3NlcSA9IHNlbnRfc2VxOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoGl0ZW0tJmd0O2wzLmlwX2lkID0gaXBfaWQ7PGJyPg0KK8KgIMKgIMKgIMKgfTxicj4NCivC oCDCoCDCoCDCoGl0ZW0tJmd0O25iX21lcmdlZCsrOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAv KiB1cGRhdGUgTUJVRiBtZXRhZGF0YSBmb3IgdGhlIG1lcmdlZCBwYWNrZXQgKi88YnI+DQorwqAg wqAgwqAgwqBwa3RfaGVhZC0mZ3Q7bmJfc2VncyArPSBwa3RfdGFpbC0mZ3Q7bmJfc2Vnczs8YnI+ DQorwqAgwqAgwqAgwqBwa3RfaGVhZC0mZ3Q7cGt0X2xlbiArPSBwa3RfdGFpbC0mZ3Q7cGt0X2xl bjs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIDE7PGJyPg0KK308YnI+DQorPGJyPg0K Ky8qPGJyPg0KKyAqIENoZWNrIGlmIHR3byBUQ1AvSVB2NCBwYWNrZXRzIGFyZSBuZWlnaGJvcnMu PGJyPg0KKyAqLzxicj4NCitzdGF0aWMgaW5saW5lIGludDxicj4NCitjaGVja19zZXFfb3B0aW9u KHN0cnVjdCBncm9fdGNwX2l0ZW0gKml0ZW0sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg c3RydWN0IHJ0ZV90Y3BfaGRyICp0Y3BoLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVp bnQzMl90IHNlbnRfc2VxLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IGlw X2lkLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVpbnQxNl90IHRjcF9obCw8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTZfdCB0Y3BfZGwsPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgdWludDE2X3QgbDJfb2Zmc2V0LDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoHVpbnQ4X3QgaXNfYXRvbWljKTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IHJ0 ZV9tYnVmICpwa3Rfb3JpZyA9IGl0ZW0tJmd0O2ZpcnN0c2VnOzxicj4NCivCoCDCoCDCoCDCoGNo YXIgKmlwaF9vcmlnOzxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBydGVfdGNwX2hkciAqdGNwaF9v cmlnOzxicj4NCivCoCDCoCDCoCDCoHVpbnQxNl90IGxlbiwgdGNwX2hsX29yaWc7PGJyPg0KKzxi cj4NCivCoCDCoCDCoCDCoGlwaF9vcmlnID0gKGNoYXIgKikocnRlX3BrdG1idWZfbXRvZChwa3Rf b3JpZywgY2hhciAqKSArPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg bDJfb2Zmc2V0ICsgcGt0X29yaWctJmd0O2wyX2xlbik7PGJyPg0KK8KgIMKgIMKgIMKgdGNwaF9v cmlnID0gKHN0cnVjdCBydGVfdGNwX2hkciAqKShpcGhfb3JpZyArIHBrdF9vcmlnLSZndDtsM19s ZW4pOzxicj4NCivCoCDCoCDCoCDCoHRjcF9obF9vcmlnID0gcGt0X29yaWctJmd0O2w0X2xlbjs8 YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgLyogQ2hlY2sgaWYgVENQIG9wdGlvbiBmaWVsZHMgZXF1 YWwgKi88YnI+DQorwqAgwqAgwqAgwqBsZW4gPSBSVEVfTUFYKHRjcF9obCwgdGNwX2hsX29yaWcp IC0gc2l6ZW9mKHN0cnVjdCBydGVfdGNwX2hkcik7PGJyPg0KK8KgIMKgIMKgIMKgaWYgKCh0Y3Bf aGwgIT0gdGNwX2hsX29yaWcpIHx8ICgobGVuICZndDsgMCkgJmFtcDsmYW1wOzxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoChtZW1jbXAodGNwaCAr IDEsIHRjcGhfb3JpZyArIDEsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbGVuKSAhPSAwKSkpPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgcmV0dXJuIDA7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoC8qIERvbiYjMzk7 dCBtZXJnZSBwYWNrZXRzIHdob3NlIERGIGJpdHMgYXJlIGRpZmZlcmVudCAqLzxicj4NCivCoCDC oCDCoCDCoGlmICh1bmxpa2VseShpdGVtLSZndDtpc19hdG9taWMgXiBpc19hdG9taWMpKTxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybiAwOzxicj4NCis8YnI+DQorwqAgwqAgwqAg wqAvKiBjaGVjayBpZiB0aGUgdHdvIHBhY2tldHMgYXJlIG5laWdoYm9ycyAqLzxicj4NCivCoCDC oCDCoCDCoGxlbiA9IHBrdF9vcmlnLSZndDtwa3RfbGVuIC0gbDJfb2Zmc2V0IC0gcGt0X29yaWct Jmd0O2wyX2xlbiAtPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcGt0X29yaWctJmd0O2wz X2xlbiAtIHRjcF9obF9vcmlnOzxicj4NCivCoCDCoCDCoCDCoGlmICgoc2VudF9zZXEgPT0gaXRl bS0mZ3Q7c2VudF9zZXEgKyBsZW4pICZhbXA7JmFtcDsgKGlzX2F0b21pYyB8fDxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoChpcF9pZCA9PSBpdGVt LSZndDtsMy5pcF9pZCArIDEpKSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiBhcHBl bmQgdGhlIG5ldyBwYWNrZXQgKi88YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm4g MTs8YnI+DQorwqAgwqAgwqAgwqBlbHNlIGlmICgoc2VudF9zZXEgKyB0Y3BfZGwgPT0gaXRlbS0m Z3Q7c2VudF9zZXEpICZhbXA7JmFtcDsgKGlzX2F0b21pYyB8fDxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoChpcF9pZCArIGl0ZW0tJmd0O25iX21l cmdlZCA9PSBpdGVtLSZndDtsMy5pcF9pZCkpKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oC8qIHByZS1wZW5kIHRoZSBuZXcgcGFja2V0ICovPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgcmV0dXJuIC0xOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqByZXR1cm4gMDs8YnI+DQorfTxi cj4NCis8YnI+DQorc3RhdGljIGlubGluZSBpbnQ8YnI+DQoraXNfY29tbW9uX3RjcF9rZXkoc3Ry dWN0IGNtbl90Y3Bfa2V5ICprMSwgc3RydWN0IGNtbl90Y3Bfa2V5ICprMik8YnI+DQorezxicj4N CivCoCDCoCDCoCDCoHJldHVybiAoIW1lbWNtcChrMSwgazIsIHNpemVvZihzdHJ1Y3QgY21uX3Rj cF9rZXkpKSk7PGJyPg0KK308YnI+DQorPGJyPg0KKyNlbmRpZjxicj4NCmRpZmYgLS1naXQgYS9s aWIvZ3JvL2dyb192eGxhbl90Y3A0LmMgYi9saWIvZ3JvL2dyb192eGxhbl90Y3A0LmM8YnI+DQpp bmRleCAzYmU0ZGViN2M3Li44MWVlYmYwZDJkIDEwMDY0NDxicj4NCi0tLSBhL2xpYi9ncm8vZ3Jv X3Z4bGFuX3RjcDQuYzxicj4NCisrKyBiL2xpYi9ncm8vZ3JvX3Z4bGFuX3RjcDQuYzxicj4NCkBA IC03LDYgKzcsNyBAQDxicj4NCsKgI2luY2x1ZGUgJmx0O3J0ZV9ldGhkZXYuaCZndDs8YnI+DQrC oCNpbmNsdWRlICZsdDtydGVfdWRwLmgmZ3Q7PGJyPg0KPGJyPg0KKyNpbmNsdWRlICZxdW90O2dy b190Y3BfaW50ZXJuYWwuaCZxdW90Ozxicj4NCsKgI2luY2x1ZGUgJnF1b3Q7Z3JvX3Z4bGFuX3Rj cDQuaCZxdW90Ozxicj4NCjxicj4NCsKgdm9pZCAqPGJyPg0KQEAgLTExNiw3ICsxMTcsNyBAQCBp bnNlcnRfbmV3X2l0ZW0oc3RydWN0IGdyb192eGxhbl90Y3A0X3RibCAqdGJsLDxicj4NCsKgIMKg IMKgIMKgIHRibC0mZ3Q7aXRlbXNbaXRlbV9pZHhdLmlubmVyX2l0ZW0uc3RhcnRfdGltZSA9IHN0 YXJ0X3RpbWU7PGJyPg0KwqAgwqAgwqAgwqAgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0uaW5uZXJf aXRlbS5uZXh0X3BrdF9pZHggPSBJTlZBTElEX0FSUkFZX0lOREVYOzxicj4NCsKgIMKgIMKgIMKg IHRibC0mZ3Q7aXRlbXNbaXRlbV9pZHhdLmlubmVyX2l0ZW0uc2VudF9zZXEgPSBzZW50X3NlcTs8 YnI+DQotwqAgwqAgwqAgwqB0YmwtJmd0O2l0ZW1zW2l0ZW1faWR4XS5pbm5lcl9pdGVtLmlwX2lk ID0gaXBfaWQ7PGJyPg0KK8KgIMKgIMKgIMKgdGJsLSZndDtpdGVtc1tpdGVtX2lkeF0uaW5uZXJf aXRlbS5sMy5pcF9pZCA9IGlwX2lkOzxicj4NCsKgIMKgIMKgIMKgIHRibC0mZ3Q7aXRlbXNbaXRl bV9pZHhdLmlubmVyX2l0ZW0ubmJfbWVyZ2VkID0gMTs8YnI+DQrCoCDCoCDCoCDCoCB0YmwtJmd0 O2l0ZW1zW2l0ZW1faWR4XS5pbm5lcl9pdGVtLmlzX2F0b21pYyA9IGlzX2F0b21pYzs8YnI+DQrC oCDCoCDCoCDCoCB0YmwtJmd0O2l0ZW1zW2l0ZW1faWR4XS5vdXRlcl9pcF9pZCA9IG91dGVyX2lw X2lkOzxicj4NCkBAIC0xNjMsMTUgKzE2NCw5IEBAIGluc2VydF9uZXdfZmxvdyhzdHJ1Y3QgZ3Jv X3Z4bGFuX3RjcDRfdGJsICp0YmwsPGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgZHN0ID0gJmFtcDso dGJsLSZndDtmbG93c1tmbG93X2lkeF0ua2V5KTs8YnI+DQo8YnI+DQotwqAgwqAgwqAgwqBydGVf ZXRoZXJfYWRkcl9jb3B5KCZhbXA7KHNyYy0mZ3Q7aW5uZXJfa2V5LmV0aF9zYWRkciksPGJyPg0K LcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgJmFtcDsoZHN0LSZndDtpbm5lcl9r ZXkuZXRoX3NhZGRyKSk7PGJyPg0KLcKgIMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJfY29weSgmYW1w OyhzcmMtJmd0O2lubmVyX2tleS5ldGhfZGFkZHIpLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCZhbXA7KGRzdC0mZ3Q7aW5uZXJfa2V5LmV0aF9kYWRkcikpOzxicj4N CivCoCDCoCDCoCDCoEFTU0lHTl9DT01NT05fVENQX0tFWSgoJmFtcDsoc3JjLSZndDtpbm5lcl9r ZXkuY21uX2tleSkpLCAoJmFtcDsoZHN0LSZndDtpbm5lcl9rZXkuY21uX2tleSkpKTs8YnI+DQrC oCDCoCDCoCDCoCBkc3QtJmd0O2lubmVyX2tleS5pcF9zcmNfYWRkciA9IHNyYy0mZ3Q7aW5uZXJf a2V5LmlwX3NyY19hZGRyOzxicj4NCsKgIMKgIMKgIMKgIGRzdC0mZ3Q7aW5uZXJfa2V5LmlwX2Rz dF9hZGRyID0gc3JjLSZndDtpbm5lcl9rZXkuaXBfZHN0X2FkZHI7PGJyPg0KLcKgIMKgIMKgIMKg ZHN0LSZndDtpbm5lcl9rZXkucmVjdl9hY2sgPSBzcmMtJmd0O2lubmVyX2tleS5yZWN2X2Fjazs8 YnI+DQotwqAgwqAgwqAgwqBkc3QtJmd0O2lubmVyX2tleS5zcmNfcG9ydCA9IHNyYy0mZ3Q7aW5u ZXJfa2V5LnNyY19wb3J0Ozxicj4NCi3CoCDCoCDCoCDCoGRzdC0mZ3Q7aW5uZXJfa2V5LmRzdF9w b3J0ID0gc3JjLSZndDtpbm5lcl9rZXkuZHN0X3BvcnQ7PGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAg ZHN0LSZndDt2eGxhbl9oZHIudnhfZmxhZ3MgPSBzcmMtJmd0O3Z4bGFuX2hkci52eF9mbGFnczs8 YnI+DQrCoCDCoCDCoCDCoCBkc3QtJmd0O3Z4bGFuX2hkci52eF92bmkgPSBzcmMtJmd0O3Z4bGFu X2hkci52eF92bmk7PGJyPg0KQEAgLTI0OCw3ICsyNDMsNyBAQCBtZXJnZV90d29fdnhsYW5fdGNw NF9wYWNrZXRzKHN0cnVjdCBncm9fdnhsYW5fdGNwNF9pdGVtICppdGVtLDxicj4NCsKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIHVpbnQxNl90IG91dGVyX2lwX2lkLDxicj4NCsKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIHVpbnQxNl90IGlwX2lkKTxicj4NCsKgezxicj4NCi3CoCDCoCDCoCDCoGlmICht ZXJnZV90d29fdGNwNF9wYWNrZXRzKCZhbXA7aXRlbS0mZ3Q7aW5uZXJfaXRlbSwgcGt0LCBjbXAs IHNlbnRfc2VxLDxicj4NCivCoCDCoCDCoCDCoGlmIChtZXJnZV90d29fdGNwX3BhY2tldHMoJmFt cDtpdGVtLSZndDtpbm5lcl9pdGVtLCBwa3QsIGNtcCwgc2VudF9zZXEsPGJyPg0KwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaXBfaWQsIHBrdC0mZ3Q7b3V0 ZXJfbDJfbGVuICs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCBwa3QtJmd0O291dGVyX2wzX2xlbikpIHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCAvKiBVcGRhdGUgdGhlIG91dGVyIElQdjQgSUQgdG8gdGhlIGxhcmdlIHZhbHVlLiAqLzxi cj4NCkBAIC0zNTcsMTMgKzM1MiwxMyBAQCBncm9fdnhsYW5fdGNwNF9yZWFzc2VtYmxlKHN0cnVj dCBydGVfbWJ1ZiAqcGt0LDxicj4NCjxicj4NCsKgIMKgIMKgIMKgIHNlbnRfc2VxID0gcnRlX2Jl X3RvX2NwdV8zMih0Y3BfaGRyLSZndDtzZW50X3NlcSk7PGJyPg0KPGJyPg0KLcKgIMKgIMKgIMKg cnRlX2V0aGVyX2FkZHJfY29weSgmYW1wOyhldGhfaGRyLSZndDtzcmNfYWRkciksICZhbXA7KGtl eS5pbm5lcl9rZXkuZXRoX3NhZGRyKSk7PGJyPg0KLcKgIMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJf Y29weSgmYW1wOyhldGhfaGRyLSZndDtkc3RfYWRkciksICZhbXA7KGtleS5pbm5lcl9rZXkuZXRo X2RhZGRyKSk7PGJyPg0KK8KgIMKgIMKgIMKgcnRlX2V0aGVyX2FkZHJfY29weSgmYW1wOyhldGhf aGRyLSZndDtzcmNfYWRkciksICZhbXA7KGtleS5pbm5lcl9rZXkuY21uX2tleS5ldGhfc2FkZHIp KTs8YnI+DQorwqAgwqAgwqAgwqBydGVfZXRoZXJfYWRkcl9jb3B5KCZhbXA7KGV0aF9oZHItJmd0 O2RzdF9hZGRyKSwgJmFtcDsoa2V5LmlubmVyX2tleS5jbW5fa2V5LmV0aF9kYWRkcikpOzxicj4N CsKgIMKgIMKgIMKgIGtleS5pbm5lcl9rZXkuaXBfc3JjX2FkZHIgPSBpcHY0X2hkci0mZ3Q7c3Jj X2FkZHI7PGJyPg0KwqAgwqAgwqAgwqAga2V5LmlubmVyX2tleS5pcF9kc3RfYWRkciA9IGlwdjRf aGRyLSZndDtkc3RfYWRkcjs8YnI+DQotwqAgwqAgwqAgwqBrZXkuaW5uZXJfa2V5LnJlY3ZfYWNr ID0gdGNwX2hkci0mZ3Q7cmVjdl9hY2s7PGJyPg0KLcKgIMKgIMKgIMKga2V5LmlubmVyX2tleS5z cmNfcG9ydCA9IHRjcF9oZHItJmd0O3NyY19wb3J0Ozxicj4NCi3CoCDCoCDCoCDCoGtleS5pbm5l cl9rZXkuZHN0X3BvcnQgPSB0Y3BfaGRyLSZndDtkc3RfcG9ydDs8YnI+DQorwqAgwqAgwqAgwqBr ZXkuaW5uZXJfa2V5LmNtbl9rZXkucmVjdl9hY2sgPSB0Y3BfaGRyLSZndDtyZWN2X2Fjazs8YnI+ DQorwqAgwqAgwqAgwqBrZXkuaW5uZXJfa2V5LmNtbl9rZXkuc3JjX3BvcnQgPSB0Y3BfaGRyLSZn dDtzcmNfcG9ydDs8YnI+DQorwqAgwqAgwqAgwqBrZXkuaW5uZXJfa2V5LmNtbl9rZXkuZHN0X3Bv cnQgPSB0Y3BfaGRyLSZndDtkc3RfcG9ydDs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCBrZXkudnhs YW5faGRyLnZ4X2ZsYWdzID0gdnhsYW5faGRyLSZndDt2eF9mbGFnczs8YnI+DQrCoCDCoCDCoCDC oCBrZXkudnhsYW5faGRyLnZ4X3ZuaSA9IHZ4bGFuX2hkci0mZ3Q7dnhfdm5pOzxicj4NCmRpZmYg LS1naXQgYS9saWIvZ3JvL2dyb192eGxhbl90Y3A0LmggYi9saWIvZ3JvL2dyb192eGxhbl90Y3A0 Lmg8YnI+DQppbmRleCA3ODMyOTQyYTY4Li44MmVhYWVlMTFlIDEwMDY0NDxicj4NCi0tLSBhL2xp Yi9ncm8vZ3JvX3Z4bGFuX3RjcDQuaDxicj4NCisrKyBiL2xpYi9ncm8vZ3JvX3Z4bGFuX3RjcDQu aDxicj4NCkBAIC01LDYgKzUsNyBAQDxicj4NCsKgI2lmbmRlZiBfR1JPX1ZYTEFOX1RDUDRfSF88 YnI+DQrCoCNkZWZpbmUgX0dST19WWExBTl9UQ1A0X0hfPGJyPg0KPGJyPg0KKyNpbmNsdWRlICZx dW90O2dyb190Y3BfaW50ZXJuYWwuaCZxdW90Ozxicj4NCsKgI2luY2x1ZGUgJnF1b3Q7Z3JvX3Rj cDQuaCZxdW90Ozxicj4NCjxicj4NCsKgI2RlZmluZSBHUk9fVlhMQU5fVENQNF9UQkxfTUFYX0lU RU1fTlVNICgxMDI0VUwgKiAxMDI0VUwpPGJyPg0KQEAgLTM2LDcgKzM3LDcgQEAgc3RydWN0IGdy b192eGxhbl90Y3A0X2Zsb3cgezxicj4NCsKgfTs8YnI+DQo8YnI+DQrCoHN0cnVjdCBncm9fdnhs YW5fdGNwNF9pdGVtIHs8YnI+DQotwqAgwqAgwqAgwqBzdHJ1Y3QgZ3JvX3RjcDRfaXRlbSBpbm5l cl9pdGVtOzxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBncm9fdGNwX2l0ZW0gaW5uZXJfaXRlbTs8 YnI+DQrCoCDCoCDCoCDCoCAvKiBJUHY0IElEIGluIHRoZSBvdXRlciBJUHY0IGhlYWRlciAqLzxi cj4NCsKgIMKgIMKgIMKgIHVpbnQxNl90IG91dGVyX2lwX2lkOzxicj4NCsKgIMKgIMKgIMKgIC8q IEluZGljYXRlIGlmIG91dGVyIElQdjQgSUQgY2FuIGJlIGlnbm9yZWQgKi88YnI+DQpkaWZmIC0t Z2l0IGEvbGliL2dyby9tZXNvbi5idWlsZCBiL2xpYi9ncm8vbWVzb24uYnVpbGQ8YnI+DQppbmRl eCBlNGZhMjk1OGJkLi4xNjQwMzE3ODkwIDEwMDY0NDxicj4NCi0tLSBhL2xpYi9ncm8vbWVzb24u YnVpbGQ8YnI+DQorKysgYi9saWIvZ3JvL21lc29uLmJ1aWxkPGJyPg0KQEAgLTMsNyArMyw5IEBA PGJyPg0KPGJyPg0KwqBzb3VyY2VzID0gZmlsZXMoPGJyPg0KwqAgwqAgwqAgwqAgwqAmIzM5O3J0 ZV9ncm8uYyYjMzk7LDxicj4NCivCoCDCoCDCoCDCoCAmIzM5O2dyb190Y3BfaW50ZXJuYWwuYyYj Mzk7LDxicj4NCsKgIMKgIMKgIMKgIMKgJiMzOTtncm9fdGNwNC5jJiMzOTssPGJyPg0KK8KgIMKg IMKgIMKgICYjMzk7Z3JvX3RjcDYuYyYjMzk7LDxicj4NCsKgIMKgIMKgIMKgIMKgJiMzOTtncm9f dWRwNC5jJiMzOTssPGJyPg0KwqAgwqAgwqAgwqAgwqAmIzM5O2dyb192eGxhbl90Y3A0LmMmIzM5 Oyw8YnI+DQrCoCDCoCDCoCDCoCDCoCYjMzk7Z3JvX3Z4bGFuX3VkcDQuYyYjMzk7LDxicj4NCmRp ZmYgLS1naXQgYS9saWIvZ3JvL3J0ZV9ncm8uYyBiL2xpYi9ncm8vcnRlX2dyby5jPGJyPg0KaW5k ZXggZTM1Mzk5ZmQ0Mi4uZDgyNGVlYmQ5MyAxMDA2NDQ8YnI+DQotLS0gYS9saWIvZ3JvL3J0ZV9n cm8uYzxicj4NCisrKyBiL2xpYi9ncm8vcnRlX2dyby5jPGJyPg0KQEAgLTgsNiArOCw3IEBAPGJy Pg0KPGJyPg0KwqAjaW5jbHVkZSAmcXVvdDtydGVfZ3JvLmgmcXVvdDs8YnI+DQrCoCNpbmNsdWRl ICZxdW90O2dyb190Y3A0LmgmcXVvdDs8YnI+DQorI2luY2x1ZGUgJnF1b3Q7Z3JvX3RjcDYuaCZx dW90Ozxicj4NCsKgI2luY2x1ZGUgJnF1b3Q7Z3JvX3VkcDQuaCZxdW90Ozxicj4NCsKgI2luY2x1 ZGUgJnF1b3Q7Z3JvX3Z4bGFuX3RjcDQuaCZxdW90Ozxicj4NCsKgI2luY2x1ZGUgJnF1b3Q7Z3Jv X3Z4bGFuX3VkcDQuaCZxdW90Ozxicj4NCkBAIC0yMCwxNCArMjEsMTYgQEAgdHlwZWRlZiB1aW50 MzJfdCAoKmdyb190YmxfcGt0X2NvdW50X2ZuKSh2b2lkICp0YmwpOzxicj4NCjxicj4NCsKgc3Rh dGljIGdyb190YmxfY3JlYXRlX2ZuIHRibF9jcmVhdGVfZm5bUlRFX0dST19UWVBFX01BWF9OVU1d ID0gezxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGdyb190Y3A0X3RibF9jcmVhdGUsIGdy b192eGxhbl90Y3A0X3RibF9jcmVhdGUsPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZ3Jv X3VkcDRfdGJsX2NyZWF0ZSwgZ3JvX3Z4bGFuX3VkcDRfdGJsX2NyZWF0ZSwgTlVMTH07PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZ3JvX3VkcDRfdGJsX2NyZWF0ZSwgZ3JvX3Z4bGFuX3Vk cDRfdGJsX2NyZWF0ZSwgZ3JvX3RjcDZfdGJsX2NyZWF0ZSwgTlVMTH07PGJyPg0KwqBzdGF0aWMg Z3JvX3RibF9kZXN0cm95X2ZuIHRibF9kZXN0cm95X2ZuW1JURV9HUk9fVFlQRV9NQVhfTlVNXSA9 IHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBncm9fdGNwNF90Ymxf ZGVzdHJveSwgZ3JvX3Z4bGFuX3RjcDRfdGJsX2Rlc3Ryb3ksPGJyPg0KwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgZ3JvX3VkcDRfdGJsX2Rlc3Ryb3ksIGdyb192eGxhbl91ZHA0 X3RibF9kZXN0cm95LDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGdy b190Y3A2X3RibF9kZXN0cm95LDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIE5VTEx9Ozxicj4NCsKgc3RhdGljIGdyb190YmxfcGt0X2NvdW50X2ZuIHRibF9wa3RfY291 bnRfZm5bUlRFX0dST19UWVBFX01BWF9OVU1dID0gezxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIGdyb190Y3A0X3RibF9wa3RfY291bnQsIGdyb192eGxhbl90Y3A0X3Ri bF9wa3RfY291bnQsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZ3Jv X3VkcDRfdGJsX3BrdF9jb3VudCwgZ3JvX3Z4bGFuX3VkcDRfdGJsX3BrdF9jb3VudCw8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBncm9fdGNwNl90YmxfcGt0X2NvdW50 LDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIE5VTEx9Ozxicj4NCjxi cj4NCsKgI2RlZmluZSBJU19JUFY0X1RDUF9QS1QocHR5cGUpIChSVEVfRVRIX0lTX0lQVjRfSERS KHB0eXBlKSAmYW1wOyZhbXA7IFw8YnI+DQpAQCAtMzUsNiArMzgsMTIgQEAgc3RhdGljIGdyb190 YmxfcGt0X2NvdW50X2ZuIHRibF9wa3RfY291bnRfZm5bUlRFX0dST19UWVBFX01BWF9OVU1dID0g ezxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICgocHR5cGUgJmFtcDsgUlRFX1BUWVBFX0w0 X0ZSQUcpICE9IFJURV9QVFlQRV9MNF9GUkFHKSAmYW1wOyZhbXA7IFw8YnI+DQrCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCAoUlRFX0VUSF9JU19UVU5ORUxfUEtUKHB0eXBlKSA9PSAwKSk8YnI+DQo8 YnI+DQorLyogR1JPIHdpdGggZXh0ZW5zaW9uIGhlYWRlcnMgaXMgbm90IHN1cHBvcnRlZCAqLzxi cj4NCisjZGVmaW5lIElTX0lQVjZfVENQX1BLVChwdHlwZSkgKFJURV9FVEhfSVNfSVBWNl9IRFIo cHR5cGUpICZhbXA7JmFtcDsgXDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCgocHR5cGUg JmFtcDsgUlRFX1BUWVBFX0w0X1RDUCkgPT0gUlRFX1BUWVBFX0w0X1RDUCkgJmFtcDsmYW1wOyBc PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgKChwdHlwZSAmYW1wOyBSVEVfUFRZUEVfTDRf RlJBRykgIT0gUlRFX1BUWVBFX0w0X0ZSQUcpICZhbXA7JmFtcDsgXDxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoChSVEVfRVRIX0lTX1RVTk5FTF9QS1QocHR5cGUpID09IDApKTxicj4NCis8 YnI+DQrCoCNkZWZpbmUgSVNfSVBWNF9VRFBfUEtUKHB0eXBlKSAoUlRFX0VUSF9JU19JUFY0X0hE UihwdHlwZSkgJmFtcDsmYW1wOyBcPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgKChwdHlw ZSAmYW1wOyBSVEVfUFRZUEVfTDRfVURQKSA9PSBSVEVfUFRZUEVfTDRfVURQKSAmYW1wOyZhbXA7 IFw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAoUlRFX0VUSF9JU19UVU5ORUxfUEtUKHB0 eXBlKSA9PSAwKSk8YnI+DQpAQCAtMTQ3LDcgKzE1NiwxMSBAQCBydGVfZ3JvX3JlYXNzZW1ibGVf YnVyc3Qoc3RydWN0IHJ0ZV9tYnVmICoqcGt0cyw8YnI+DQrCoCDCoCDCoCDCoCAvKiBhbGxvY2F0 ZSBhIHJlYXNzZW1ibHkgdGFibGUgZm9yIFRDUC9JUHY0IEdSTyAqLzxicj4NCsKgIMKgIMKgIMKg IHN0cnVjdCBncm9fdGNwNF90YmwgdGNwX3RibDs8YnI+DQrCoCDCoCDCoCDCoCBzdHJ1Y3QgZ3Jv X3RjcDRfZmxvdyB0Y3BfZmxvd3NbUlRFX0dST19NQVhfQlVSU1RfSVRFTV9OVU1dOzxicj4NCi3C oCDCoCDCoCDCoHN0cnVjdCBncm9fdGNwNF9pdGVtIHRjcF9pdGVtc1tSVEVfR1JPX01BWF9CVVJT VF9JVEVNX05VTV0gPSB7ezB9IH07PGJyPg0KK8KgIMKgIMKgIMKgc3RydWN0IGdyb190Y3BfaXRl bSB0Y3BfaXRlbXNbUlRFX0dST19NQVhfQlVSU1RfSVRFTV9OVU1dID0ge3swfSB9Ozxicj4NCis8 YnI+DQorwqAgwqAgwqAgwqBzdHJ1Y3QgZ3JvX3RjcDZfdGJsIHRjcDZfdGJsOzxicj4NCivCoCDC oCDCoCDCoHN0cnVjdCBncm9fdGNwNl9mbG93IHRjcDZfZmxvd3NbUlRFX0dST19NQVhfQlVSU1Rf SVRFTV9OVU1dOzxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBncm9fdGNwX2l0ZW0gdGNwNl9pdGVt c1tSVEVfR1JPX01BWF9CVVJTVF9JVEVNX05VTV0gPSB7ezB9IH07PGJyPg0KPGJyPg0KwqAgwqAg wqAgwqAgLyogYWxsb2NhdGUgYSByZWFzc2VtYmx5IHRhYmxlIGZvciBVRFAvSVB2NCBHUk8gKi88 YnI+DQrCoCDCoCDCoCDCoCBzdHJ1Y3QgZ3JvX3VkcDRfdGJsIHVkcF90Ymw7PGJyPg0KQEAgLTE3 MSwxMCArMTg0LDEwIEBAIHJ0ZV9ncm9fcmVhc3NlbWJsZV9idXJzdChzdHJ1Y3QgcnRlX21idWYg Kipwa3RzLDxicj4NCsKgIMKgIMKgIMKgIGludDMyX3QgcmV0Ozxicj4NCsKgIMKgIMKgIMKgIHVp bnQxNl90IGksIHVucHJvY2Vzc19udW0gPSAwLCBuYl9hZnRlcl9ncm8gPSBuYl9wa3RzOzxicj4N CsKgIMKgIMKgIMKgIHVpbnQ4X3QgZG9fdGNwNF9ncm8gPSAwLCBkb192eGxhbl90Y3BfZ3JvID0g MCwgZG9fdWRwNF9ncm8gPSAwLDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGRvX3Z4bGFu X3VkcF9ncm8gPSAwOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGRvX3Z4bGFuX3VkcF9n cm8gPSAwLCBkb190Y3A2X2dybyA9IDA7PGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgaWYgKHVubGlr ZWx5KChwYXJhbS0mZ3Q7Z3JvX3R5cGVzICZhbXA7IChSVEVfR1JPX0lQVjRfVlhMQU5fVENQX0lQ VjQgfDxicj4NCi3CoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoFJURV9HUk9fVENQX0lQVjQgfDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoFJURV9HUk9fVENQX0lQVjQg fCBSVEVfR1JPX1RDUF9JUFY2IHw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBSVEVfR1JPX0lQVjRfVlhMQU5fVURQX0lQVjQg fDxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIFJURV9HUk9fVURQX0lQVjQpKSA9PSAwKSk8YnI+DQrCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCByZXR1cm4gbmJfcGt0czs8YnI+DQpAQCAtMjM2LDYgKzI0OSwxOCBAQCBydGVfZ3Jv X3JlYXNzZW1ibGVfYnVyc3Qoc3RydWN0IHJ0ZV9tYnVmICoqcGt0cyw8YnI+DQrCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCBkb191ZHA0X2dybyA9IDE7PGJyPg0KwqAgwqAgwqAgwqAgfTxicj4NCjxi cj4NCivCoCDCoCDCoCDCoGlmIChwYXJhbS0mZ3Q7Z3JvX3R5cGVzICZhbXA7IFJURV9HUk9fVENQ X0lQVjYpIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBmb3IgKGkgPSAwOyBpICZsdDsg aXRlbV9udW07IGkrKyk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0 Y3A2X2Zsb3dzW2ldLnN0YXJ0X2luZGV4ID0gSU5WQUxJRF9BUlJBWV9JTkRFWDs8YnI+DQorPGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGNwNl90YmwuZmxvd3MgPSB0Y3A2X2Zsb3dzOzxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRjcDZfdGJsLml0ZW1zID0gdGNwNl9pdGVtczs8 YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0Y3A2X3RibC5mbG93X251bSA9IDA7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGNwNl90YmwuaXRlbV9udW0gPSAwOzxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHRjcDZfdGJsLm1heF9mbG93X251bSA9IGl0ZW1fbnVtOzxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHRjcDZfdGJsLm1heF9pdGVtX251bSA9IGl0ZW1fbnVt Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGRvX3RjcDZfZ3JvID0gMTs8YnI+DQorwqAg wqAgwqAgwqB9PGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgZm9yIChpID0gMDsgaSAmbHQ7IG5iX3Br dHM7IGkrKykgezxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIC8qPGJyPg0KQEAgLTI3Niw2 ICszMDEsMTQgQEAgcnRlX2dyb19yZWFzc2VtYmxlX2J1cnN0KHN0cnVjdCBydGVfbWJ1ZiAqKnBr dHMsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg bmJfYWZ0ZXJfZ3JvLS07PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg ZWxzZSBpZiAocmV0ICZsdDsgMCk8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCB1bnByb2Nlc3NfcGt0c1t1bnByb2Nlc3NfbnVtKytdID0gcGt0c1tp XTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9IGVsc2UgaWYgKElTX0lQVjZfVENQX1BL VChwa3RzW2ldLSZndDtwYWNrZXRfdHlwZSkgJmFtcDsmYW1wOzxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGRvX3RjcDZfZ3JvKSB7PGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmV0ID0gZ3JvX3RjcDZfcmVhc3NlbWJs ZShwa3RzW2ldLCAmYW1wO3RjcDZfdGJsLCAwKTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqBpZiAocmV0ICZndDsgMCk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAvKiBtZXJnZSBzdWNjZXNzZnVsbHkgKi88YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBuYl9hZnRlcl9n cm8tLTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBlbHNlIGlmIChy ZXQgJmx0OyAwKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoHVucHJvY2Vzc19wa3RzW3VucHJvY2Vzc19udW0rK10gPSBwa3RzW2ldOzxicj4NCsKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIH0gZWxzZTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIHVucHJvY2Vzc19wa3RzW3VucHJvY2Vzc19udW0rK10gPSBwa3RzW2ldOzxi cj4NCsKgIMKgIMKgIMKgIH08YnI+DQpAQCAtMjgzLDkgKzMxNiwxNyBAQCBydGVfZ3JvX3JlYXNz ZW1ibGVfYnVyc3Qoc3RydWN0IHJ0ZV9tYnVmICoqcGt0cyw8YnI+DQrCoCDCoCDCoCDCoCBpZiAo KG5iX2FmdGVyX2dybyAmbHQ7IG5iX3BrdHMpPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqB8fCAodW5wcm9jZXNzX251bSAmbHQ7IG5iX3BrdHMpKSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgaSA9IDA7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyogQ29weSB1bnBy b2Nlc3NlZCBwYWNrZXRzICovPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKHVucHJv Y2Vzc19udW0gJmd0OyAwKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgbWVtY3B5KCZhbXA7cGt0c1tpXSwgdW5wcm9jZXNzX3BrdHMsPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc2l6ZW9mKHN0 cnVjdCBydGVfbWJ1ZiAqKSAqPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdW5wcm9jZXNzX251bSk7PGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaSA9IHVucHJvY2Vzc19udW07PGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgfTxicj4NCis8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAv KiBGbHVzaCBhbGwgcGFja2V0cyBmcm9tIHRoZSB0YWJsZXMgKi88YnI+DQrCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCBpZiAoZG9fdnhsYW5fdGNwX2dybykgezxicj4NCi3CoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoGkgPSBncm9fdnhsYW5fdGNwNF90YmxfdGltZW91dF9mbHVzaCgm YW1wO3Z4bGFuX3RjcF90YmwsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgaSArPSBncm9fdnhsYW5fdGNwNF90YmxfdGltZW91dF9mbHVzaCgmYW1wO3Z4bGFuX3RjcF90 YmwsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgMCwgcGt0cywgbmJfcGt0cyk7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgfTxicj4NCjxicj4NCkBAIC0zMDQsMTMgKzM0NSwxMSBAQCBydGVfZ3JvX3JlYXNzZW1ibGVf YnVyc3Qoc3RydWN0IHJ0ZV9tYnVmICoqcGt0cyw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCBpICs9IGdyb191ZHA0X3RibF90aW1lb3V0X2ZsdXNoKCZhbXA7dWRwX3Ri bCwgMCw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCAmYW1wO3BrdHNbaV0sIG5iX3BrdHMgLSBpKTs8YnI+DQrCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCB9PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgLyogQ29weSB1bnBy b2Nlc3NlZCBwYWNrZXRzICovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKHVucHJv Y2Vzc19udW0gJmd0OyAwKSB7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgbWVtY3B5KCZhbXA7cGt0c1tpXSwgdW5wcm9jZXNzX3BrdHMsPGJyPg0KLcKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc2l6ZW9mKHN0 cnVjdCBydGVfbWJ1ZiAqKSAqPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdW5wcm9jZXNzX251bSk7PGJyPg0KKzxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChkb190Y3A2X2dybykgezxicj4NCivCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGkgKz0gZ3JvX3RjcDZfdGJsX3RpbWVvdXRfZmx1c2go JmFtcDt0Y3A2X3RibCwgMCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAmYW1wO3BrdHNbaV0sIG5iX3BrdHMgLSBpKTs8YnI+ DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg bmJfYWZ0ZXJfZ3JvID0gaSArIHVucHJvY2Vzc19udW07PGJyPg0KwqAgwqAgwqAgwqAgfTxicj4N Cjxicj4NCsKgIMKgIMKgIMKgIHJldHVybiBuYl9hZnRlcl9ncm87PGJyPg0KQEAgLTMyMywxMyAr MzYyLDEzIEBAIHJ0ZV9ncm9fcmVhc3NlbWJsZShzdHJ1Y3QgcnRlX21idWYgKipwa3RzLDxicj4N CsKgezxicj4NCsKgIMKgIMKgIMKgIHN0cnVjdCBydGVfbWJ1ZiAqdW5wcm9jZXNzX3BrdHNbbmJf cGt0c107PGJyPg0KwqAgwqAgwqAgwqAgc3RydWN0IGdyb19jdHggKmdyb19jdHggPSBjdHg7PGJy Pg0KLcKgIMKgIMKgIMKgdm9pZCAqdGNwX3RibCwgKnVkcF90YmwsICp2eGxhbl90Y3BfdGJsLCAq dnhsYW5fdWRwX3RibDs8YnI+DQorwqAgwqAgwqAgwqB2b2lkICp0Y3BfdGJsLCAqdWRwX3RibCwg KnZ4bGFuX3RjcF90YmwsICp2eGxhbl91ZHBfdGJsLCAqdGNwNl90Ymw7PGJyPg0KwqAgwqAgwqAg wqAgdWludDY0X3QgY3VycmVudF90aW1lOzxicj4NCsKgIMKgIMKgIMKgIHVpbnQxNl90IGksIHVu cHJvY2Vzc19udW0gPSAwOzxicj4NCi3CoCDCoCDCoCDCoHVpbnQ4X3QgZG9fdGNwNF9ncm8sIGRv X3Z4bGFuX3RjcF9ncm8sIGRvX3VkcDRfZ3JvLCBkb192eGxhbl91ZHBfZ3JvOzxicj4NCivCoCDC oCDCoCDCoHVpbnQ4X3QgZG9fdGNwNF9ncm8sIGRvX3Z4bGFuX3RjcF9ncm8sIGRvX3VkcDRfZ3Jv LCBkb192eGxhbl91ZHBfZ3JvLCBkb190Y3A2X2dybzs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCBp ZiAodW5saWtlbHkoKGdyb19jdHgtJmd0O2dyb190eXBlcyAmYW1wOyAoUlRFX0dST19JUFY0X1ZY TEFOX1RDUF9JUFY0IHw8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBSVEVfR1JPX1RDUF9JUFY0IHw8YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBSVEVfR1JP X1RDUF9JUFY0IHwgUlRFX0dST19UQ1BfSVBWNiB8PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgUlRFX0dST19JUFY0X1ZYTEFO X1VEUF9JUFY0IHw8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCBSVEVfR1JPX1VEUF9JUFY0KSkgPT0gMCkpPGJyPg0KwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuIG5iX3BrdHM7PGJyPg0KQEAgLTMzOCw2ICszNzcsNyBA QCBydGVfZ3JvX3JlYXNzZW1ibGUoc3RydWN0IHJ0ZV9tYnVmICoqcGt0cyw8YnI+DQrCoCDCoCDC oCDCoCB2eGxhbl90Y3BfdGJsID0gZ3JvX2N0eC0mZ3Q7dGJsc1tSVEVfR1JPX0lQVjRfVlhMQU5f VENQX0lQVjRfSU5ERVhdOzxicj4NCsKgIMKgIMKgIMKgIHVkcF90YmwgPSBncm9fY3R4LSZndDt0 YmxzW1JURV9HUk9fVURQX0lQVjRfSU5ERVhdOzxicj4NCsKgIMKgIMKgIMKgIHZ4bGFuX3VkcF90 YmwgPSBncm9fY3R4LSZndDt0YmxzW1JURV9HUk9fSVBWNF9WWExBTl9VRFBfSVBWNF9JTkRFWF07 PGJyPg0KK8KgIMKgIMKgIMKgdGNwNl90YmwgPSBncm9fY3R4LSZndDt0YmxzW1JURV9HUk9fVENQ X0lQVjZfSU5ERVhdOzxicj4NCjxicj4NCsKgIMKgIMKgIMKgIGRvX3RjcDRfZ3JvID0gKGdyb19j dHgtJmd0O2dyb190eXBlcyAmYW1wOyBSVEVfR1JPX1RDUF9JUFY0KSA9PTxicj4NCsKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIFJURV9HUk9fVENQX0lQVjQ7PGJyPg0KQEAgLTM0Nyw2ICszODcsNyBA QCBydGVfZ3JvX3JlYXNzZW1ibGUoc3RydWN0IHJ0ZV9tYnVmICoqcGt0cyw8YnI+DQrCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBSVEVfR1JPX1VEUF9JUFY0Ozxicj4NCsKgIMKgIMKgIMKgIGRvX3Z4 bGFuX3VkcF9ncm8gPSAoZ3JvX2N0eC0mZ3Q7Z3JvX3R5cGVzICZhbXA7IFJURV9HUk9fSVBWNF9W WExBTl9VRFBfSVBWNCkgPT08YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBSVEVfR1JPX0lQ VjRfVlhMQU5fVURQX0lQVjQ7PGJyPg0KK8KgIMKgIMKgIMKgZG9fdGNwNl9ncm8gPSAoZ3JvX2N0 eC0mZ3Q7Z3JvX3R5cGVzICZhbXA7IFJURV9HUk9fVENQX0lQVjYpID09IFJURV9HUk9fVENQX0lQ VjY7PGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgY3VycmVudF90aW1lID0gcnRlX3JkdHNjKCk7PGJy Pg0KPGJyPg0KQEAgLTM3MSw2ICs0MTIsMTEgQEAgcnRlX2dyb19yZWFzc2VtYmxlKHN0cnVjdCBy dGVfbWJ1ZiAqKnBrdHMsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg aWYgKGdyb191ZHA0X3JlYXNzZW1ibGUocGt0c1tpXSwgdWRwX3RibCw8YnI+DQrCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCBjdXJyZW50X3RpbWUpICZsdDsgMCk8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB1bnByb2Nlc3NfcGt0c1t1bnByb2Nlc3NfbnVtKytdID0g cGt0c1tpXTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9IGVsc2UgaWYgKElTX0lQVjZf VENQX1BLVChwa3RzW2ldLSZndDtwYWNrZXRfdHlwZSkgJmFtcDsmYW1wOzxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGRvX3RjcDZfZ3JvKSB7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGdyb190Y3A2X3JlYXNz ZW1ibGUocGt0c1tpXSwgdGNwNl90YmwsPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgY3VycmVudF90aW1l KSAmbHQ7IDApPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgdW5wcm9jZXNzX3BrdHNbdW5wcm9jZXNzX251bSsrXSA9IHBrdHNbaV07PGJyPg0KwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgfSBlbHNlPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgdW5wcm9jZXNzX3BrdHNbdW5wcm9jZXNzX251bSsrXSA9IHBrdHNbaV07PGJy Pg0KwqAgwqAgwqAgwqAgfTxicj4NCkBAIC00MjYsNiArNDcyLDE1IEBAIHJ0ZV9ncm9fdGltZW91 dF9mbHVzaCh2b2lkICpjdHgsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgZ3JvX2N0eC0mZ3Q7dGJsc1tSVEVfR1JPX1VEUF9JUFY0X0lOREVYXSw8 YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBmbHVz aF90aW1lc3RhbXAsPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgJmFtcDtvdXRbbnVtXSwgbGVmdF9uYl9vdXQpOzxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoGxlZnRfbmJfb3V0ID0gbWF4X25iX291dCAtIG51bTs8YnI+DQorwqAgwqAgwqAg wqB9PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGlmICgoZ3JvX3R5cGVzICZhbXA7IFJURV9HUk9f VENQX0lQVjYpICZhbXA7JmFtcDsgbGVmdF9uYl9vdXQgJmd0OyAwKSB7PGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgbnVtICs9IGdyb190Y3A2X3RibF90aW1lb3V0X2ZsdXNoKDxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGdyb19jdHgtJmd0 O3RibHNbUlRFX0dST19UQ1BfSVBWNl9JTkRFWF0sPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZmx1c2hfdGltZXN0YW1wLDxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCZhbXA7b3V0W251bV0sIGxl ZnRfbmJfb3V0KTs8YnI+DQorPGJyPg0KwqAgwqAgwqAgwqAgfTxicj4NCjxicj4NCsKgIMKgIMKg IMKgIHJldHVybiBudW07PGJyPg0KZGlmZiAtLWdpdCBhL2xpYi9ncm8vcnRlX2dyby5oIGIvbGli L2dyby9ydGVfZ3JvLmg8YnI+DQppbmRleCA5ZjllZDQ5MzVhLi5jODNkZmQ5YWQxIDEwMDY0NDxi cj4NCi0tLSBhL2xpYi9ncm8vcnRlX2dyby5oPGJyPg0KKysrIGIvbGliL2dyby9ydGVfZ3JvLmg8 YnI+DQpAQCAtMzgsNiArMzgsOSBAQCBleHRlcm4gJnF1b3Q7QyZxdW90OyB7PGJyPg0KwqAjZGVm aW5lIFJURV9HUk9fSVBWNF9WWExBTl9VRFBfSVBWNF9JTkRFWCAzPGJyPg0KwqAjZGVmaW5lIFJU RV9HUk9fSVBWNF9WWExBTl9VRFBfSVBWNCAoMVVMTCAmbHQ7Jmx0OyBSVEVfR1JPX0lQVjRfVlhM QU5fVURQX0lQVjRfSU5ERVgpPGJyPg0KwqAvKiombHQ7IFZ4TEFOIFVEUC9JUHY0IEdSTyBmbGFn LiAqLzxicj4NCisjZGVmaW5lIFJURV9HUk9fVENQX0lQVjZfSU5ERVggNDxicj4NCisjZGVmaW5l IFJURV9HUk9fVENQX0lQVjYgKDFVTEwgJmx0OyZsdDsgUlRFX0dST19UQ1BfSVBWNl9JTkRFWCk8 YnI+DQorLyoqJmx0OyBUQ1AvSVB2NiBHUk8gZmxhZy4gKi88YnI+DQo8YnI+DQrCoC8qKjxicj4N CsKgICogU3RydWN0dXJlIHVzZWQgdG8gY3JlYXRlIEdSTyBjb250ZXh0IG9iamVjdHMgb3IgdXNl ZCB0byBwYXNzPGJyPg0KLS0gPGJyPg0KMi4yNS4xPGJyPsKgPC9ibG9ja3F1b3RlPjxibG9ja3F1 b3RlIGNsYXNzPSJnbWFpbF9xdW90ZSIgc3R5bGU9Im1hcmdpbjowcHggMHB4IDBweCAwLjhleDti b3JkZXItbGVmdDoxcHggc29saWQgcmdiKDIwNCwyMDQsMjA0KTtwYWRkaW5nLWxlZnQ6MWV4Ij48 YmxvY2txdW90ZSBjbGFzcz0iZ21haWxfcXVvdGUiIHN0eWxlPSJtYXJnaW46MHB4IDBweCAwcHgg MC44ZXg7Ym9yZGVyLWxlZnQ6MXB4IHNvbGlkIHJnYigyMDQsMjA0LDIwNCk7cGFkZGluZy1sZWZ0 OjFleCI+PGRpdj5IaSBKaXlhdSwgSSBoYXZlIHVwZGF0ZWQgdGhlIHJldmlldyBjb21tZW50cy4g VGVzdGVkIEdSTyBmb3IgYm90aCB2NCBhbmQgdjYuwqAgSSB3aWxsIHVwZGF0ZSB0aGUgZ2VuZXJp Y19yZWNlaXZlX29mZmxvYWRfbGliLnJzdCBhbmQgcmVsZWFzZSBub3RlIGluIHN1YnNlcXVlbnQg Y2hhbmdlLiBXb3VsZCBiZSBncmVhdCBpZiB5b3UgY2FuIHJldmlldyB0aGUgY3VycmVudCBjaGFu Z2VzIGJ5IHRoZW4uIDwvZGl2PjwvYmxvY2txdW90ZT48L2Jsb2NrcXVvdGU+PC9kaXY+PC9kaXY+ DQo= --000000000000b205c405fded8460--