From ec6253849afbb4e9e7c9714b93cab098b26c087e Mon Sep 17 00:00:00 2001 From: Yurchenko Darya Date: Mon, 23 Nov 2015 20:10:02 +0300 Subject: [PATCH] [IMPROVE] added wifi consumption Change-Id: I8e465c6ca1c5c9743ec71c9e10eb1dca2d6b5ed2 Signed-off-by: Yurchenko Darya --- energy/debugfs_energy.c | 51 ++++++++++++++ energy/energy.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++- energy/energy.h | 6 +- 3 files changed, 237 insertions(+), 2 deletions(-) diff --git a/energy/debugfs_energy.c b/energy/debugfs_energy.c index 0278445..eb9c7a0 100644 --- a/energy/debugfs_energy.c +++ b/energy/debugfs_energy.c @@ -119,8 +119,47 @@ static u64 fw_apps(void) } +/* wifi recv */ +static DEFINE_RATIONAL(wf_recv_coef); +static u64 wf_recv_system(void) +{ + u64 byte = 0; + + get_parameter_energy(PE_WF_RECV_SYSTEM, &byte, sizeof(byte)); + + return div_u64(byte * wf_recv_coef.num, wf_recv_coef.denom); +} + +static u64 wf_recv_apps(void) +{ + u64 byte = 0; + + get_parameter_energy(PE_WF_RECV_APPS, &byte, sizeof(byte)); + + return div_u64(byte * wf_recv_coef.num, wf_recv_coef.denom); +} +/* wifi send */ +static DEFINE_RATIONAL(wf_send_coef); + +static u64 wf_send_system(void) +{ + u64 byte = 0; + + get_parameter_energy(PE_WF_SEND_SYSTEM, &byte, sizeof(byte)); + + return div_u64(byte * wf_send_coef.num, wf_send_coef.denom); +} + +static u64 wf_send_apps(void) +{ + u64 byte = 0; + + get_parameter_energy(PE_WF_SEND_APPS, &byte, sizeof(byte)); + + return div_u64(byte * wf_send_coef.num, wf_send_coef.denom); +} /* ============================================================================ * === PARAMETERS === @@ -211,6 +250,18 @@ struct param_data parameters[] = { .coef = &fw_coef, .system = fw_system, .apps = fw_apps + }, + { + .name = "wf_recv", + .coef = &wf_recv_coef, + .system = wf_recv_system, + .apps = wf_recv_apps + }, + { + .name = "wf_send", + .coef = &wf_send_coef, + .system = wf_send_system, + .apps = wf_send_apps } }; diff --git a/energy/energy.c b/energy/energy.c index 3192f19..d9eca32 100644 --- a/energy/energy.c +++ b/energy/energy.c @@ -30,6 +30,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -130,6 +135,11 @@ struct energy_data { /*for sys_write */ atomic64_t bytes_written; + /*for recvmsg*/ + atomic64_t bytes_recv; + + /* for sock_send */ + atomic64_t bytes_send; }; static sspt_feature_id_t feature_id = SSPT_FEATURE_ID_BAD; @@ -142,6 +152,8 @@ static void init_ed(struct energy_data *ed) cpus_time_init(&ed->ct, 0); atomic64_set(&ed->bytes_read, 0); atomic64_set(&ed->bytes_written, 0); + atomic64_set(&ed->bytes_recv, 0); + atomic64_set(&ed->bytes_send, 0); } static void uninit_ed(struct energy_data *ed) @@ -149,6 +161,8 @@ static void uninit_ed(struct energy_data *ed) cpus_time_init(&ed->ct, 0); atomic64_set(&ed->bytes_read, 0); atomic64_set(&ed->bytes_written, 0); + atomic64_set(&ed->bytes_recv, 0); + atomic64_set(&ed->bytes_send, 0); } static void *create_ed(void) @@ -439,10 +453,153 @@ static struct kretprobe sys_write_krp = { +/* ============================================================================ + * = wifi = + * ============================================================================ + */ +static bool check_wlan0(struct socket *sock) +{ + /* FIXME: hardcode interface */ + const char *name_intrf = "wlan0"; + + if (sock->sk->sk_dst_cache && + sock->sk->sk_dst_cache->dev && + !strcmp(sock->sk->sk_dst_cache->dev->name, name_intrf)) + return true; + + return false; +} + +static int entry_handler_wf_sock(struct kretprobe_instance *ri, + struct pt_regs *regs) +{ + bool *ok = (bool *)ri->data; + struct socket *socket = (struct socket *)swap_get_karg(regs, 0); + + *ok = check_wlan0(socket); + + return 0; +} + +static int ret_handler_wf_sock_recv(struct kretprobe_instance *ri, + struct pt_regs *regs) +{ + int ret = regs_return_value(regs); + + if (ret > 0) { + bool ok = *(bool *)ri->data; + + if (ok) { + struct energy_data *ed; + + ed = get_energy_data(current); + if (ed) + atomic64_add(ret, &ed->bytes_recv); + atomic64_add(ret, &ed_system.bytes_recv); + } + } + + return 0; +} + +static int ret_handler_wf_sock_send(struct kretprobe_instance *ri, + struct pt_regs *regs) +{ + int ret = regs_return_value(regs); + + if (ret > 0) { + bool ok = *(bool *)ri->data; + + if (ok) { + struct energy_data *ed; + + ed = get_energy_data(current); + if (ed) + atomic64_add(ret, &ed->bytes_send); + atomic64_add(ret, &ed_system.bytes_send); + } + } + + return 0; +} + +static struct kretprobe sock_recv_krp = { + .entry_handler = entry_handler_wf_sock, + .handler = ret_handler_wf_sock_recv, + .data_size = sizeof(bool) +}; + +static struct kretprobe sock_send_krp = { + .entry_handler = entry_handler_wf_sock, + .handler = ret_handler_wf_sock_send, + .data_size = sizeof(bool) +}; + +static int energy_wifi_once(void) +{ + const char *sym; + + sym = "sock_recvmsg"; + sock_recv_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym); + if (sock_recv_krp.kp.addr == NULL) + goto not_found; + + sym = "sock_sendmsg"; + sock_send_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym); + if (sock_send_krp.kp.addr == NULL) + goto not_found; + + return 0; + +not_found: + printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym); + return -ESRCH; +} + +static int energy_wifi_flag = 0; + +static int energy_wifi_set(void) +{ + int ret; + + ret = swap_register_kretprobe(&sock_recv_krp); + if (ret) { + pr_err("swap_register_kretprobe(sock_recv_krp) ret=%d\n" ,ret); + return ret; + } + + ret = swap_register_kretprobe(&sock_send_krp); + if (ret) { + pr_err("swap_register_kretprobe(sock_send_krp) ret=%d\n" ,ret); + swap_unregister_kretprobe(&sock_recv_krp); + } + + energy_wifi_flag = 1; + + return ret; +} + +static void energy_wifi_unset(void) +{ + if (energy_wifi_flag == 0) + return; + + swap_unregister_kretprobe(&sock_send_krp); + swap_unregister_kretprobe(&sock_recv_krp); + + energy_wifi_flag = 0; +} + + + + + enum parameter_type { PT_CPU, PT_READ, - PT_WRITE + PT_WRITE, + PT_WF_RECV, + PT_WF_SEND }; struct cmd_pt { @@ -473,6 +630,12 @@ static void callback_for_proc(struct sspt_proc *proc, void *data) case PT_WRITE: *val += atomic64_read(&ed->bytes_written); break; + case PT_WF_RECV: + *val += atomic64_read(&ed->bytes_recv); + break; + case PT_WF_SEND: + *val += atomic64_read(&ed->bytes_send); + break; default: break; } @@ -527,12 +690,24 @@ int get_parameter_energy(enum parameter_energy pe, void *buf, size_t sz) case PE_WRITE_SYSTEM: *val = atomic64_read(&ed_system.bytes_written); break; + case PE_WF_RECV_SYSTEM: + *val = atomic64_read(&ed_system.bytes_recv); + break; + case PE_WF_SEND_SYSTEM: + *val = atomic64_read(&ed_system.bytes_send); + break; case PE_READ_APPS: current_parameter_apps(PT_READ, buf, sz); break; case PE_WRITE_APPS: current_parameter_apps(PT_WRITE, buf, sz); break; + case PE_WF_RECV_APPS: + current_parameter_apps(PT_WF_RECV, buf, sz); + break; + case PE_WF_SEND_APPS: + current_parameter_apps(PT_WF_SEND, buf, sz); + break; default: ret = -EINVAL; break; @@ -569,6 +744,8 @@ int do_set_energy(void) goto unregister_sys_write; } + energy_wifi_set(); + /* TODO: check return value */ lcd_set_energy(); @@ -586,6 +763,7 @@ unregister_sys_write: void do_unset_energy(void) { lcd_unset_energy(); + energy_wifi_unset(); swap_unregister_kretprobe(&switch_to_krp); swap_unregister_kretprobe(&sys_write_krp); @@ -668,6 +846,8 @@ int energy_once(void) if (sys_write_krp.kp.addr == NULL) goto not_found; + energy_wifi_once(); + return 0; not_found: diff --git a/energy/energy.h b/energy/energy.h index 9626d1d..e2f7812 100644 --- a/energy/energy.h +++ b/energy/energy.h @@ -39,7 +39,11 @@ enum parameter_energy { PE_READ_SYSTEM, /**< number of bytes are read by system */ PE_WRITE_SYSTEM, /**< number of bytes are write by system */ PE_READ_APPS, /**< number of bytes are read by apps */ - PE_WRITE_APPS /**< number of bytes are write by apps*/ + PE_WRITE_APPS, /**< number of bytes are write by apps */ + PE_WF_RECV_SYSTEM, /**< number of bytes are receive by system through wifi */ + PE_WF_SEND_SYSTEM, /**< number of bytes are send by system through wifi */ + PE_WF_RECV_APPS, /**< number of bytes are receive by apps through wifi */ + PE_WF_SEND_APPS, /**< number of bytes are send by apps through wifi */ }; -- 2.7.4