int bastet_comm_write(u8 *msg, u32 len) { BASTET_MSG_STRU *pMsg = NULL; VOS_UINT32 ulLength = 0; if (NULL == msg) { return -1; } ulLength = sizeof(BASTET_MSG_STRU) + BST_MAX_WRITE_PAYLOAD - 4; pMsg = (BASTET_MSG_STRU *)PS_ALLOC_MSG_WITH_HEADER_LEN(ACPU_PID_BASTET_COMM, ulLength); if (NULL == pMsg) { BASTET_LOGE("PS_ALLOC_MSG_WITH_HEADER_LEN failed"); return -1; } pMsg->ulReceiverPid = UEPS_PID_BASTET; PS_MEM_CPY((VOS_VOID*)pMsg->aucValue, msg, len); pMsg->usLen = len; if (PS_SEND_MSG(ACPU_PID_BASTET_COMM, pMsg) != 0) { BASTET_LOGE("PS_SEND_MSG failed"); return -1; } return 0; }
/* * Function is called when application starts bastet proxy. */ int start_bastet_sock(struct bst_set_sock_sync_delay *init_prop) { int err = 0; struct sock *sk; struct bst_sock_id *guide = &init_prop->guide; sk = get_sock_by_fd_pid(guide->fd, guide->pid); if (NULL == sk) { BASTET_LOGE("can not find sock by fd: %d pid: %d", guide->fd, guide->pid); return -ENOENT; } if (TCP_ESTABLISHED != sk->sk_state) { BASTET_LOGE("sk: %p sk_state is not TCP_ESTABLISHED", sk); sock_put(sk); return -EPERM; } if (tcp_sk(sk)->repair) { BASTET_LOGE("sk: %p in repair mode", sk); sock_put(sk); return -EPERM; } BASTET_LOGI("sk: %p", sk); err = do_start_bastet_sock(sk, init_prop); sock_put(sk); return err; }
int bastet_sync_prop_stop(struct bst_sock_comm_prop *comm_prop) { struct sock *sk; struct bastet_sock *bsk; sk = get_sock_by_comm_prop(comm_prop); if (NULL == sk) { BASTET_LOGE("can not find sock by lport: %d, lIp: %pI4, rport: %d, rIp: %pI4", comm_prop->local_port, &comm_prop->local_ip, comm_prop->remote_port, &comm_prop->remote_ip); return -ENOENT; } if (sk->sk_state == TCP_TIME_WAIT) { BASTET_LOGE("sk: %p not expected time wait sock", sk); inet_twsk_put(inet_twsk(sk)); return -EPERM; } BASTET_LOGI("sk: %p", sk); bsk = sk->bastet; if (bsk) { if (bsk->bastet_sock_state != BST_SOCK_NOT_USED) { bsk->user_ctrl = BST_USER_START; bsk->bastet_sock_state = BST_SOCK_VALID; setup_sock_sync_delay_timer(sk); } } sock_put(sk); return 0; }
/* * Set sock sync properties. */ int set_tcp_sock_sync_prop(struct bst_set_sock_sync_prop *set_prop) { int err = 0; struct sock *sk; struct bastet_sock *bsk; struct bst_sock_comm_prop *guide = &set_prop->guide; sk = get_sock_by_comm_prop(guide); if (NULL == sk) { BASTET_LOGE("can not find sock by lport: %d, lIp: %pI4, rport: %d, rIp: %pI4", guide->local_port, &guide->local_ip, guide->remote_port, &guide->remote_ip); return -ENOENT; } if (sk->sk_state == TCP_TIME_WAIT) { BASTET_LOGE("sk: %p not expected time wait sock", sk); inet_twsk_put(inet_twsk(sk)); return -EPERM; } bsk = sk->bastet; if (NULL == bsk) { BASTET_LOGE("sk: %p not expected bastet null", sk); err = -EPERM; goto out_put; } BASTET_LOGI("sk: %p", sk); spin_lock_bh(&sk->sk_lock.slock); if (NULL != bsk->sync_p) { BASTET_LOGE("sk: %p has a pending sock set", sk); err = -EPERM; goto out_unlock; } cancel_sock_bastet_timer(sk); if (sock_owned_by_user(sk)) { err = setup_sock_sync_set_timer(sk, &set_prop->sync_prop); goto out_unlock; } sock_set_internal(sk, &set_prop->sync_prop); out_unlock: spin_unlock_bh(&sk->sk_lock.slock); adjust_traffic_flow_by_sock(sk, set_prop->sync_prop.tx, set_prop->sync_prop.rx); out_put: sock_put(sk); return err; }
/* * Close sock, when modem bastet fails this sock. */ int set_tcp_sock_closed(struct bst_sock_comm_prop *guide) { int err = 0; struct sock *sk; struct bastet_sock *bsk; sk = get_sock_by_comm_prop(guide); if (NULL == sk) { BASTET_LOGE("can not find sock by lport: %d, lIp: %pI4, rport: %d, rIp: %pI4", guide->local_port, &guide->local_ip, guide->remote_port, &guide->remote_ip); return -ENOENT; } if (sk->sk_state == TCP_TIME_WAIT) { BASTET_LOGE("sk: %p not expected time wait sock", sk); inet_twsk_put(inet_twsk(sk)); return -EPERM; } bsk = sk->bastet; if (NULL == bsk) { BASTET_LOGE("sk: %p not expected bastet null", sk); err = -EPERM; goto out_put; } BASTET_LOGI("sk: %p", sk); spin_lock_bh(&sk->sk_lock.slock); if (BST_SOCK_INVALID != bsk->bastet_sock_state && BST_SOCK_UPDATING != bsk->bastet_sock_state) { BASTET_LOGE("sk: %p sync_current_state: %d not expected", sk, bsk->bastet_sock_state); goto out_unlock; } cancel_sock_bastet_timer(sk); bsk->bastet_sock_state = BST_SOCK_NOT_USED; if (sock_owned_by_user(sk)) { setup_sock_sync_close_timer(sk); goto out_unlock; } set_sock_close_internal(sk); out_unlock: spin_unlock_bh(&sk->sk_lock.slock); out_put: sock_put(sk); return err; }
int bastet_sync_prop_start(struct bst_set_sock_sync_prop *set_prop) { int err = 0; struct sock *sk; struct bastet_sock *bsk; struct bst_sock_comm_prop *guide = &set_prop->guide; sk = get_sock_by_comm_prop(guide); if (NULL == sk) { BASTET_LOGE("can not find sock by lport: %d, lIp: %pI4, rport: %d, rIp: %pI4", guide->local_port, &guide->local_ip, guide->remote_port, &guide->remote_ip); return -ENOENT; } if (sk->sk_state == TCP_TIME_WAIT) { BASTET_LOGE("sk: %p not expected time wait sock", sk); inet_twsk_put(inet_twsk(sk)); return -EPERM; } bsk = sk->bastet; if (NULL == bsk) { BASTET_LOGE("sk: %p not expected bastet null", sk); err = -EPERM; goto out_put; } BASTET_LOGI("sk: %p", sk); if (NULL != bsk->sync_p) { BASTET_LOGE("sk: %p has a pending sock set", sk); err = -EPERM; goto out; } sock_set_internal(sk, &set_prop->sync_prop); bastet_sync_prop_cancel(sk); bsk->flag = true; BASTET_LOGI("wake up bastet wq"); wake_up_interruptible(&bsk->wq); out: adjust_traffic_flow_by_sock(sk, set_prop->sync_prop.tx, set_prop->sync_prop.rx); out_put: sock_put(sk); return err; }
/* * Generate bastet sock in sock struct. */ static int create_bastet_sock(struct sock *sk, struct bst_set_sock_sync_delay *init_prop) { struct bastet_sock *bsk; bsk = kmalloc(sizeof(*bsk), GFP_KERNEL); if (NULL == bsk) { BASTET_LOGE("kmalloc failed"); return -ENOMEM; } bsk->bastet_sock_state = BST_SOCK_NOT_USED; bsk->bastet_timer_event = BST_TMR_EVT_INVALID; bsk->user_ctrl = BST_USER_STOP; bsk->fd = init_prop->guide.fd; bsk->pid = init_prop->guide.pid; bsk->proxy_id = init_prop->proxy_id; bsk->bastet_timeout = 0; bsk->last_sock_active_time_point = jiffies; bsk->sync_p = NULL; bsk->need_repair = 0; bsk->delay_sync_time_section = msecs_to_jiffies(init_prop->hold_time); setup_timer(&bsk->bastet_timer, bastet_sock_bastet_timeout, (unsigned long)sk); skb_queue_head_init(&bsk->recv_queue); bsk->recv_len = 0; init_waitqueue_head(&bsk->wq); bsk->flag = false; sk->bastet = bsk; return 0; }
/* * Get modem id and rab id. */ int get_modem_rab_id(struct bst_modem_rab_id *info) { struct net_device *dev; RNIC_SPEC_CTX_STRU *spec_net_card; RNIC_PDP_CTX_STRU *pdp_addr; RNIC_NETCARD_DEV_INFO_STRU *priv; if (NULL == info) { return -EINVAL; } dev = dev_get_by_name(&init_net, cur_netdev_name); if (NULL == dev) { return -ENOENT; } priv = (RNIC_NETCARD_DEV_INFO_STRU *)netdev_priv(dev); spec_net_card = RNIC_GetSpecNetCardCtxAddr(priv->enRmNetId); pdp_addr = &spec_net_card->stPdpCtx; if (RNIC_PDP_REG_STATUS_ACTIVE != pdp_addr->stIpv4PdpInfo.enRegStatus) { BASTET_LOGE("Ipv4 pdp reg status inactive"); return -EPERM; } info->modem_id = spec_net_card->enModemId; /* Bastet only running in IPv4 mode, * so, get IPv4 Pdp info */ info->rab_id = pdp_addr->stIpv4PdpInfo.ucRabId; return 0; }
int bastet_ccorereset_cbfun(DRV_RESET_CB_MOMENT_E eparam, int userdata) { if (MDRV_RESET_CB_BEFORE == eparam) { BASTET_LOGE("MDRV_RESET_CB_BEFORE"); bastet_modem_reset_notify(); } return BSP_RESET_OK; }
/* * Function is called when application stops bastet proxy. */ int stop_bastet_sock(struct bst_sock_id *guide) { struct sock *sk; struct bastet_sock *bsk; u8 sync_state; sk = get_sock_by_fd_pid(guide->fd, guide->pid); if (NULL == sk) { BASTET_LOGE("can not find sock by fd: %d pid: %d", guide->fd, guide->pid); return -ENOENT; } bsk = sk->bastet; if (NULL == bsk) { BASTET_LOGE("sk: %p not expected bastet null", sk); sock_put(sk); return -EPERM; } BASTET_LOGI("sk: %p", sk); spin_lock_bh(&sk->sk_lock.slock); bsk->user_ctrl = BST_USER_STOP; sync_state = bsk->bastet_sock_state; switch (sync_state) { case BST_SOCK_VALID: bsk->bastet_sock_state = BST_SOCK_NOT_USED; cancel_sock_bastet_timer(sk); break; case BST_SOCK_INVALID: request_sock_sync(sk); break; default: break; } spin_unlock_bh(&sk->sk_lock.slock); sock_put(sk); return 0; }
/* * Set socket sync hold time */ int set_sock_sync_hold_time(struct bst_set_sock_sync_delay hold_delay) { struct sock *sk = NULL; struct bastet_sock *bsk = NULL; unsigned long orig_delay = 0; unsigned long expire = 0; sk = get_sock_by_fd_pid(hold_delay.guide.fd, hold_delay.guide.pid); if (NULL == sk) { BASTET_LOGE("can not find sock by fd: %d pid: %d", hold_delay.guide.fd, hold_delay.guide.pid); return -ENOENT; } bsk = sk->bastet; if (NULL == bsk) { BASTET_LOGE("sk: %p not expected bastet null", sk); sock_put(sk); return -EPERM; } BASTET_LOGI("hold_time=%u", hold_delay.hold_time); orig_delay = bsk->delay_sync_time_section; bsk->delay_sync_time_section = msecs_to_jiffies(hold_delay.hold_time); if (timer_pending(&bsk->bastet_timer)) { if (orig_delay < bsk->delay_sync_time_section) { BASTET_LOGI("screen off to on"); expire = bsk->last_sock_active_time_point + bsk->delay_sync_time_section; } else { BASTET_LOGI("screen on to off"); if (time_after(jiffies, bsk->last_sock_active_time_point + bsk->delay_sync_time_section)) { BASTET_LOGI("need to timeout right now"); expire = jiffies; } else { expire = bsk->last_sock_active_time_point + bsk->delay_sync_time_section; } } bsk->bastet_timeout = expire; mod_timer(&bsk->bastet_timer, expire); } sock_put(sk); return 0; }
/* * Function is called when application prepare bastet proxy. */ int prepare_bastet_sock(struct bst_set_sock_sync_delay *sync_prop) { int err = 0; struct sock *sk; struct bastet_sock *bsk; sk = get_sock_by_fd_pid(sync_prop->guide.fd, sync_prop->guide.pid); if (NULL == sk) { BASTET_LOGE("can not find sock by fd: %d pid: %d", sync_prop->guide.fd, sync_prop->guide.pid); return -ENOENT; } if (TCP_ESTABLISHED != sk->sk_state) { BASTET_LOGE("sk: %p sk_state is not TCP_ESTABLISHED", sk); sock_put(sk); return -EPERM; } if (tcp_sk(sk)->repair) { BASTET_LOGE("sk: %p in repair mode", sk); sock_put(sk); return -EPERM; } BASTET_LOGI("sk: %p", sk); bsk = sk->bastet; if (NULL == bsk) { err = create_bastet_sock(sk, sync_prop); if (err < 0) { sock_put(sk); return err; } bsk = sk->bastet; } sock_put(sk); return err; }
/* * BST_TMR_REQ_SOCK_SYNC timeout. * Request sync time is up, but sock sync properties still invalid. * Usually, daemon should set sock sync properties before timeout. */ static void request_sock_bastet_timeout(struct sock *sk) { struct bastet_sock *bsk = sk->bastet; /* Accurating time */ if (time_after(bsk->bastet_timeout, jiffies)) { sk_reset_timer(sk, &bsk->bastet_timer, bsk->bastet_timeout); return; } /* We must reset timer event, bastet_delay_sock_sync_notify depends on it * this code must be put after accurating time */ bsk->bastet_timer_event = BST_TMR_EVT_INVALID; if (BST_SOCK_UPDATING != bsk->bastet_sock_state){ BASTET_LOGE("sk: %p state: %d not expected", sk, bsk->bastet_sock_state); return; } /* Try reuqest timer again */ if (bsk->sync_retry) { request_sock_sync(sk); return; } /* If goes here, bastet sock sync failed, * Send or recv data anyway. */ BASTET_LOGE("sk: %p request timeout", sk); if (BST_USER_START == bsk->user_ctrl) { /* Before send or recv data, set state to BST_SOCK_VALID*/ bsk->bastet_sock_state = BST_SOCK_VALID; process_sock_send_and_recv(sk); } else { bsk->bastet_sock_state = BST_SOCK_NOT_USED; } }
/* * Get sock common properties. */ int get_tcp_sock_comm_prop(struct bst_get_sock_comm_prop *get_prop) { struct sock *sk; struct bst_sock_id *guide = &get_prop->guide; sk = get_sock_by_fd_pid(guide->fd, guide->pid); if (NULL == sk) { BASTET_LOGE("can not find sock by fd: %d pid: %d", guide->fd, guide->pid); return -ENOENT; } if (TCP_ESTABLISHED != sk->sk_state) { BASTET_LOGE("sk: %p sk_state not expected", sk); sock_put(sk); return -EPERM; } BASTET_LOGI("sk: %p", sk); bastet_get_comm_prop(sk, &get_prop->comm_prop); sock_put(sk); return 0; }
void bastet_comm_recv(MsgBlock *pMsg) { u32 len = 0; BASTET_MSG_STRU *pTmpMsg = (BASTET_MSG_STRU *)pMsg; if (NULL == pMsg) { BASTET_LOGE("MsgBlock is empty"); return; } len = pTmpMsg->usLen; if (len > BST_MAX_WRITE_PAYLOAD) { len = BST_MAX_WRITE_PAYLOAD; } post_indicate_packet(BST_IND_HISICOM, pTmpMsg->aucValue, len); }
/* * BST_TMR_SET_SOCK_SYNC timeout. */ static void set_sock_bastet_timeout(struct sock *sk) { struct bastet_sock *bsk = sk->bastet; bsk->bastet_timer_event = BST_TMR_EVT_INVALID; if (NULL == bsk->sync_p) { BASTET_LOGE("sk: %p not expected null sync prop", sk); return; } sock_set_internal(sk, bsk->sync_p); kfree(bsk->sync_p); bsk->sync_p = NULL; }
int get_tcp_bastet_sock_state(struct bst_get_bastet_sock_state *get_prop) { struct sock *sk; struct bst_sock_id *guide = &get_prop->guide; sk = get_sock_by_fd_pid(guide->fd, guide->pid); if (NULL == sk) { BASTET_LOGE("can not find sock by fd: %d pid: %d", guide->fd, guide->pid); return -ENOENT; } BASTET_LOGI("sk: %p", sk); get_prop->sync_state = get_bastet_sock_state(sk); sock_put(sk); return 0; }
/* * Bastet sock timeout, include all bastet time events. */ static void bastet_sock_bastet_timeout(unsigned long data) { int event; struct sock *sk = (struct sock *)data; struct bastet_sock *bsk = sk->bastet; BASTET_LOGI("sk: %p time event: %d", sk, bsk->bastet_timer_event); bh_lock_sock(sk); /* Include in lock */ event = bsk->bastet_timer_event; if (sock_owned_by_user(sk)) { /* Try again later */ if (BST_TMR_DELAY_SOCK_SYNC == event) { bastet_wakelock_acquire_timeout(BST_SKIP_SOCK_OWNER_TIME + BST_WAKELOCK_TIMEOUT); } sk_reset_timer(sk, &bsk->bastet_timer, jiffies + BST_SKIP_SOCK_OWNER_TIME); goto out_unlock; } switch(event){ case BST_TMR_REQ_SOCK_SYNC: request_sock_bastet_timeout(sk); break; case BST_TMR_SET_SOCK_SYNC: set_sock_bastet_timeout(sk); break; case BST_TMR_DELAY_SOCK_SYNC: delay_sock_bastet_timeout(sk); break; case BST_TMR_CLOSE_SOCK: close_sock_bastet_timeout(sk); break; default: BASTET_LOGE("sk: %p invalid time event: %d", sk, event); break; } sk_mem_reclaim(sk); out_unlock: bh_unlock_sock(sk); sock_put(sk); }
/* * BST_TMR_DELAY_SOCK_SYNC timeout. * If sock is ready, get sock sync properties and post them to daemon */ static void delay_sock_bastet_timeout(struct sock *sk) { int err; struct bst_set_sock_sync_prop sock_p; struct bastet_sock *bsk = sk->bastet; /* Accurating time */ if (time_after(bsk->bastet_timeout, jiffies)) { sk_reset_timer(sk, &bsk->bastet_timer, bsk->bastet_timeout); return; } /* We must reset timer event, bastet_delay_sock_sync_notify depends on it * this code must be put after accurating time */ bsk->bastet_timer_event = BST_TMR_EVT_INVALID; /* In repair mode or userspace needs repair, do not sync sock */ if (unlikely(tcp_sk(sk)->repair || bsk->need_repair)) { BASTET_LOGE("sk: %p in repair mode", sk); return; } if (TCP_ESTABLISHED != sk->sk_state) { BASTET_LOGE("sk: %p sk_state is not TCP_ESTABLISHED", sk); return; } if (BST_SOCK_VALID != bsk->bastet_sock_state) { BASTET_LOGE("sk: %p state: %d not expected", sk, bsk->bastet_sock_state); return; } /* Sock owner has used since last setup */ if (time_after(bsk->last_sock_active_time_point + bsk->delay_sync_time_section, jiffies)) { setup_sock_sync_delay_timer(sk); return; } /* Sock owner has some data unacked, * Coming ack would trigger delay timer again */ if (!tcp_write_queue_empty(sk)) { BASTET_LOGI("sk: %p has sent data not acked", sk); post_indicate_packet(BST_IND_TRIGGER_THAW, &bsk->pid, sizeof(pid_t)); return; } /* Sock owner has some data to recv, do not sync. * If sock owner has none recv action, * delay timer should be stopped. */ if (!skb_queue_empty(&sk->sk_receive_queue)) { BASTET_LOGI("sk: %p has received data in queue", sk); bsk->last_sock_active_time_point = jiffies; setup_sock_sync_delay_timer(sk); post_indicate_packet(BST_IND_TRIGGER_THAW, &bsk->pid, sizeof(pid_t)); return; } memset(&sock_p, 0, sizeof(struct bst_set_sock_sync_prop)); bastet_get_comm_prop(sk, &sock_p.guide); bastet_get_sock_prop(sk, &sock_p.sync_prop); err = post_indicate_packet(BST_IND_SOCK_SYNC_PROP, &sock_p, sizeof(sock_p)); if (!err) { /* if post success */ bsk->bastet_sock_state = BST_SOCK_INVALID; } }