// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2023,Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * RMNET PERF UDP framework
 *
 */

#include <linux/types.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <linux/hashtable.h>
#include <linux/log2.h>
#include <linux/workqueue.h>
#include <linux/refcount.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/udp.h>
#include <net/sock.h>
#include "rmnet_private.h"
#include "rmnet_perf_udp.h"
#define DATARMNET15dbec5cc0 ((0x16a8+1565-0x14f5))
#define DATARMNET1b69f5599a ((0xdf7+6169-0x241c))
#define DATARMNETe19b881e3e ((0xeb7+1158-0x132d))
#define DATARMNET98862aed95 \
	(const_ilog2(DATARMNETe19b881e3e))
enum{DATARMNETcffce1f6da,DATARMNET1d79c7ae4b,DATARMNETf1cd747d89,
DATARMNETf5e31b47ad,DATARMNETbaf32ca0ac,};struct DATARMNETee0c11924c{union{
__be32 DATARMNETdfe430c2d6;struct in6_addr DATARMNET815cbb4bf5;};union{__be32 
DATARMNET2cb607d686;struct in6_addr DATARMNETc3f31215b7;};union{struct{__be16 
DATARMNET08e913477e;__be16 DATARMNETda7f7fa492;};u32 DATARMNET556bcfcf8f;};u8 
DATARMNET0d956cc77a;};struct DATARMNETac2887e8c4{struct hlist_node hash;struct 
rcu_head DATARMNET28bfe9e6ad;struct DATARMNETee0c11924c DATARMNET54338da2ff;
struct sock*DATARMNETa3e9a18f1b;unsigned long DATARMNET763f2e5fac;u8 
DATARMNET1717afebc7;};struct DATARMNET451f84b309{struct delayed_work 
DATARMNET190b4452e8;bool DATARMNETcd94e0d3c7;};static DEFINE_SPINLOCK(
DATARMNETa125272ee8);static DEFINE_HASHTABLE(DATARMNET187c01aba9,
DATARMNET98862aed95);static u32 DATARMNETe0c4a54a69;static struct 
DATARMNET451f84b309 DATARMNET3ed0b852e9;static u64 DATARMNETf41987fea1[
DATARMNETbaf32ca0ac];module_param_array_named(rmnet_perf_udp_stat,
DATARMNETf41987fea1,ullong,NULL,(0xcb7+5769-0x221c));static void 
DATARMNET19b3edd6de(u32 DATARMNET248f120dd5){if(DATARMNET248f120dd5<
DATARMNETbaf32ca0ac)DATARMNETf41987fea1[DATARMNET248f120dd5]+=(0xd26+209-0xdf6);
}static bool DATARMNETa8d347a4e6(struct DATARMNETac2887e8c4*DATARMNET63b1a086d5,
unsigned long DATARMNET763f2e5fac){unsigned long DATARMNETc2d5c71ce1;
DATARMNETc2d5c71ce1=msecs_to_jiffies(DATARMNET15dbec5cc0);if(DATARMNET763f2e5fac
-DATARMNET63b1a086d5->DATARMNET763f2e5fac>DATARMNETc2d5c71ce1)return true;return
 false;}static void DATARMNETfcb3ce7715(struct rcu_head*DATARMNET5d432e897f){
struct DATARMNETac2887e8c4*DATARMNET63b1a086d5;DATARMNET63b1a086d5=container_of(
DATARMNET5d432e897f,struct DATARMNETac2887e8c4,DATARMNET28bfe9e6ad);if(!
IS_ERR_OR_NULL(DATARMNET63b1a086d5->DATARMNETa3e9a18f1b))sock_put(
DATARMNET63b1a086d5->DATARMNETa3e9a18f1b);kfree(DATARMNET63b1a086d5);}static 
bool DATARMNET18d263f0ec(bool DATARMNETe78ad140cc){struct DATARMNETac2887e8c4*
DATARMNET63b1a086d5;struct hlist_node*DATARMNET0386f6f82a;unsigned long 
DATARMNET763f2e5fac;int DATARMNET5c2fd31d7b;DATARMNET763f2e5fac=jiffies;
hash_for_each_safe(DATARMNET187c01aba9,DATARMNET5c2fd31d7b,DATARMNET0386f6f82a,
DATARMNET63b1a086d5,hash){if(DATARMNET63b1a086d5->DATARMNET1717afebc7)continue;
if(DATARMNETe78ad140cc||DATARMNETa8d347a4e6(DATARMNET63b1a086d5,
DATARMNET763f2e5fac)){DATARMNET63b1a086d5->DATARMNET1717afebc7=(0xd26+209-0xdf6)
;hash_del_rcu(&DATARMNET63b1a086d5->hash);call_rcu(&DATARMNET63b1a086d5->
DATARMNET28bfe9e6ad,DATARMNETfcb3ce7715);DATARMNET19b3edd6de(DATARMNETf1cd747d89
);DATARMNETe0c4a54a69--;}}return!!DATARMNETe0c4a54a69;}static void 
DATARMNET47ed281d61(struct work_struct*DATARMNET190b4452e8){struct 
DATARMNET451f84b309*DATARMNET3a3a7762bb;unsigned long DATARMNETfb0677cc3c;bool 
DATARMNET6e1c466378;DATARMNET3a3a7762bb=container_of(to_delayed_work(
DATARMNET190b4452e8),struct DATARMNET451f84b309,DATARMNET190b4452e8);
spin_lock_irqsave(&DATARMNETa125272ee8,DATARMNETfb0677cc3c);DATARMNET6e1c466378=
DATARMNET18d263f0ec(DATARMNET3a3a7762bb->DATARMNETcd94e0d3c7);if(
DATARMNET6e1c466378){unsigned long DATARMNETf71ef1b8da;DATARMNETf71ef1b8da=
msecs_to_jiffies(DATARMNET1b69f5599a);schedule_delayed_work(&DATARMNET3a3a7762bb
->DATARMNET190b4452e8,DATARMNETf71ef1b8da);}spin_unlock_irqrestore(&
DATARMNETa125272ee8,DATARMNETfb0677cc3c);}static bool DATARMNET47899a016a(struct
 DATARMNETee0c11924c*DATARMNETae0905b0b3,struct DATARMNETee0c11924c*
DATARMNETdb49f21565){if(DATARMNETae0905b0b3->DATARMNET0d956cc77a!=
DATARMNETdb49f21565->DATARMNET0d956cc77a||DATARMNETae0905b0b3->
DATARMNET08e913477e!=DATARMNETdb49f21565->DATARMNET08e913477e||
DATARMNETae0905b0b3->DATARMNETda7f7fa492!=DATARMNETdb49f21565->
DATARMNETda7f7fa492)return false;if(DATARMNETae0905b0b3->DATARMNET0d956cc77a==
(0xd11+230-0xdf3))return DATARMNETae0905b0b3->DATARMNETdfe430c2d6==
DATARMNETdb49f21565->DATARMNETdfe430c2d6&&DATARMNETae0905b0b3->
DATARMNET2cb607d686==DATARMNETdb49f21565->DATARMNET2cb607d686;return!
ipv6_addr_cmp(&DATARMNETae0905b0b3->DATARMNET815cbb4bf5,&DATARMNETdb49f21565->
DATARMNET815cbb4bf5)&&!ipv6_addr_cmp(&DATARMNETae0905b0b3->DATARMNETc3f31215b7,&
DATARMNETdb49f21565->DATARMNETc3f31215b7);}static struct DATARMNETac2887e8c4*
DATARMNET7b1084dc09(struct DATARMNETee0c11924c*DATARMNET3396919a68)__must_hold(&
DATARMNETa125272ee8){struct DATARMNETac2887e8c4*DATARMNET63b1a086d5;
DATARMNET63b1a086d5=kzalloc(sizeof(*DATARMNET63b1a086d5),GFP_ATOMIC);if(!
DATARMNET63b1a086d5){DATARMNET19b3edd6de(DATARMNET1d79c7ae4b);return NULL;}
INIT_HLIST_NODE(&DATARMNET63b1a086d5->hash);memcpy(&DATARMNET63b1a086d5->
DATARMNET54338da2ff,DATARMNET3396919a68,sizeof(*DATARMNET3396919a68));
DATARMNET63b1a086d5->DATARMNET763f2e5fac=jiffies;hash_add_rcu(
DATARMNET187c01aba9,&DATARMNET63b1a086d5->hash,DATARMNET3396919a68->
DATARMNET556bcfcf8f);DATARMNET19b3edd6de(DATARMNETcffce1f6da);if(!
DATARMNETe0c4a54a69){unsigned long DATARMNETf71ef1b8da;DATARMNETf71ef1b8da=
msecs_to_jiffies(DATARMNET1b69f5599a);schedule_delayed_work(&DATARMNET3ed0b852e9
.DATARMNET190b4452e8,DATARMNETf71ef1b8da);}DATARMNETe0c4a54a69++;return 
DATARMNET63b1a086d5;}static struct DATARMNETac2887e8c4*DATARMNET270a2369fc(
struct DATARMNETee0c11924c*DATARMNET3396919a68)__must_hold(RCU){struct 
DATARMNETac2887e8c4*DATARMNET63b1a086d5;unsigned long DATARMNETfb0677cc3c;
spin_lock_irqsave(&DATARMNETa125272ee8,DATARMNETfb0677cc3c);
hash_for_each_possible_rcu(DATARMNET187c01aba9,DATARMNET63b1a086d5,hash,
DATARMNET3396919a68->DATARMNET556bcfcf8f){if(DATARMNET63b1a086d5->
DATARMNET1717afebc7)continue;if(DATARMNET47899a016a(&DATARMNET63b1a086d5->
DATARMNET54338da2ff,DATARMNET3396919a68))goto DATARMNETbf4095f79e;}
DATARMNET63b1a086d5=DATARMNET7b1084dc09(DATARMNET3396919a68);DATARMNETbf4095f79e
:spin_unlock_irqrestore(&DATARMNETa125272ee8,DATARMNETfb0677cc3c);return 
DATARMNET63b1a086d5;}static struct sock*DATARMNETa9a99daddb(struct 
DATARMNETee0c11924c*DATARMNET3396919a68,struct sk_buff*DATARMNET543491eb0f){
struct sock*DATARMNET370b0f4269;if(DATARMNET3396919a68->DATARMNET0d956cc77a==
(0xd11+230-0xdf3))DATARMNET370b0f4269=__udp4_lib_lookup(dev_net(
DATARMNET543491eb0f->dev),DATARMNET3396919a68->DATARMNETdfe430c2d6,
DATARMNET3396919a68->DATARMNET08e913477e,DATARMNET3396919a68->
DATARMNET2cb607d686,DATARMNET3396919a68->DATARMNETda7f7fa492,inet_iif(
DATARMNET543491eb0f),(0xd2d+202-0xdf7),&udp_table,NULL);else DATARMNET370b0f4269
=__udp6_lib_lookup(dev_net(DATARMNET543491eb0f->dev),&DATARMNET3396919a68->
DATARMNET815cbb4bf5,DATARMNET3396919a68->DATARMNET08e913477e,&
DATARMNET3396919a68->DATARMNETc3f31215b7,DATARMNET3396919a68->
DATARMNETda7f7fa492,inet6_iif(DATARMNET543491eb0f),(0xd2d+202-0xdf7),&udp_table,
NULL);if(DATARMNET370b0f4269&&!refcount_inc_not_zero(&DATARMNET370b0f4269->
sk_refcnt))DATARMNET370b0f4269=NULL;return DATARMNET370b0f4269;}static void 
DATARMNET991df48508(struct DATARMNETac2887e8c4*DATARMNET63b1a086d5,struct 
sk_buff*DATARMNET543491eb0f)__must_hold(RCU){struct rmnet_skb_cb*
DATARMNET1ec4882bf7=RMNET_SKB_CB(DATARMNET543491eb0f);DATARMNET63b1a086d5->
DATARMNET763f2e5fac=jiffies;if(IS_ERR(DATARMNET63b1a086d5->DATARMNETa3e9a18f1b))
{DATARMNET1ec4882bf7->tethered=true;return;}if(!DATARMNET63b1a086d5->
DATARMNETa3e9a18f1b){DATARMNET63b1a086d5->DATARMNETa3e9a18f1b=
DATARMNETa9a99daddb(&DATARMNET63b1a086d5->DATARMNET54338da2ff,
DATARMNET543491eb0f);if(!DATARMNET63b1a086d5->DATARMNETa3e9a18f1b){
DATARMNET19b3edd6de(DATARMNETf5e31b47ad);DATARMNET63b1a086d5->
DATARMNETa3e9a18f1b=ERR_PTR(-EINVAL);DATARMNET1ec4882bf7->tethered=true;return;}
}}void DATARMNET2a6d02a6a5(struct sk_buff*DATARMNET543491eb0f){struct 
DATARMNETee0c11924c DATARMNET3396919a68={};struct DATARMNETac2887e8c4*
DATARMNET63b1a086d5;struct udphdr*DATARMNETa1abb4897c;if(!
skb_transport_header_was_set(DATARMNET543491eb0f)||DATARMNET543491eb0f->
ip_summed==CHECKSUM_NONE)return;DATARMNETa1abb4897c=udp_hdr(DATARMNET543491eb0f)
;DATARMNET3396919a68.DATARMNET08e913477e=DATARMNETa1abb4897c->source;
DATARMNET3396919a68.DATARMNETda7f7fa492=DATARMNETa1abb4897c->dest;if(
DATARMNET543491eb0f->protocol==htons(ETH_P_IP)){struct iphdr*DATARMNET86f1f2cdc9
=ip_hdr(DATARMNET543491eb0f);DATARMNET3396919a68.DATARMNETdfe430c2d6=
DATARMNET86f1f2cdc9->saddr;DATARMNET3396919a68.DATARMNET2cb607d686=
DATARMNET86f1f2cdc9->daddr;DATARMNET3396919a68.DATARMNET0d956cc77a=
(0xd11+230-0xdf3);}else{struct ipv6hdr*DATARMNETbf55123e5b=ipv6_hdr(
DATARMNET543491eb0f);memcpy(&DATARMNET3396919a68.DATARMNET815cbb4bf5,&
DATARMNETbf55123e5b->saddr,sizeof(DATARMNETbf55123e5b->saddr));memcpy(&
DATARMNET3396919a68.DATARMNETc3f31215b7,&DATARMNETbf55123e5b->daddr,sizeof(
DATARMNETbf55123e5b->daddr));DATARMNET3396919a68.DATARMNET0d956cc77a=
(0xd03+244-0xdf1);}rcu_read_lock();DATARMNET63b1a086d5=DATARMNET270a2369fc(&
DATARMNET3396919a68);if(DATARMNET63b1a086d5){if(likely(!DATARMNETa8d347a4e6(
DATARMNET63b1a086d5,jiffies)))DATARMNET991df48508(DATARMNET63b1a086d5,
DATARMNET543491eb0f);}rcu_read_unlock();}void DATARMNET5ecc30669c(struct sk_buff
*DATARMNET543491eb0f){struct DATARMNETee0c11924c DATARMNET3396919a68={};struct 
DATARMNETac2887e8c4*DATARMNET63b1a086d5;struct udphdr*DATARMNETa1abb4897c;if(!
skb_transport_header_was_set(DATARMNET543491eb0f))return;DATARMNETa1abb4897c=
udp_hdr(DATARMNET543491eb0f);DATARMNET3396919a68.DATARMNET08e913477e=
DATARMNETa1abb4897c->dest;DATARMNET3396919a68.DATARMNETda7f7fa492=
DATARMNETa1abb4897c->source;if(DATARMNET543491eb0f->protocol==htons(ETH_P_IP)){
struct iphdr*DATARMNET86f1f2cdc9=ip_hdr(DATARMNET543491eb0f);DATARMNET3396919a68
.DATARMNETdfe430c2d6=DATARMNET86f1f2cdc9->daddr;DATARMNET3396919a68.
DATARMNET2cb607d686=DATARMNET86f1f2cdc9->saddr;DATARMNET3396919a68.
DATARMNET0d956cc77a=(0xd11+230-0xdf3);}else{struct ipv6hdr*DATARMNETbf55123e5b=
ipv6_hdr(DATARMNET543491eb0f);memcpy(&DATARMNET3396919a68.DATARMNET815cbb4bf5,&
DATARMNETbf55123e5b->daddr,sizeof(DATARMNETbf55123e5b->daddr));memcpy(&
DATARMNET3396919a68.DATARMNETc3f31215b7,&DATARMNETbf55123e5b->saddr,sizeof(
DATARMNETbf55123e5b->saddr));DATARMNET3396919a68.DATARMNET0d956cc77a=
(0xd03+244-0xdf1);}rcu_read_lock();DATARMNET63b1a086d5=DATARMNET270a2369fc(&
DATARMNET3396919a68);if(DATARMNET63b1a086d5){if(likely(!DATARMNETa8d347a4e6(
DATARMNET63b1a086d5,jiffies)))DATARMNET991df48508(DATARMNET63b1a086d5,
DATARMNET543491eb0f);}rcu_read_unlock();}int DATARMNETe80a33d544(void){
INIT_DELAYED_WORK(&DATARMNET3ed0b852e9.DATARMNET190b4452e8,DATARMNET47ed281d61);
return(0xd2d+202-0xdf7);}void DATARMNET4b5170a1ef(void){cancel_delayed_work_sync
(&DATARMNET3ed0b852e9.DATARMNET190b4452e8);DATARMNET3ed0b852e9.
DATARMNETcd94e0d3c7=true;schedule_delayed_work(&DATARMNET3ed0b852e9.
DATARMNET190b4452e8,(0xd2d+202-0xdf7));cancel_delayed_work_sync(&
DATARMNET3ed0b852e9.DATARMNET190b4452e8);}