Skip to content

the achievement of sockmap based on strp_init

magnate3 edited this page Jan 17, 2020 · 4 revisions

1、 smap_init_sock

static int smap_init_sock(struct smap_psock *psock, struct sock *sk) {

  • static const struct strp_callbacks cb = {

  • .rcv_msg = smap_read_sock_strparser,

  • .parse_msg = smap_parse_func_strparser,

  • .read_sock_done = smap_read_sock_done, }; return strp_init(&psock->strp, sk, &cb); }

smap_init_sock

  • static void smap_read_sock_strparser(struct strparser *strp,

  • struct sk_buff *skb)

  • {

  • struct smap_psock *psock;

  • rcu_read_lock();

  • psock = container_of(strp, struct smap_psock, strp);

  • smap_do_verdict(psock, skb);

  • rcu_read_unlock();

  • }

2、 strp_init

  • int strp_init(struct strparser *strp, struct sock *csk,
  • struct strp_callbacks *cb)
  • {
  • struct socket *sock = csk->sk_socket;
  • if (!cb || !cb->rcv_msg || !cb->parse_msg)
  • return -EINVAL;
  • if (!sock->ops->read_sock || !sock->ops->peek_len)
  • return -EAFNOSUPPORT;
  • memset(strp, 0, sizeof(*strp));
  • strp->sk = csk;
  • setup_timer(&strp->rx_msg_timer, strp_rx_msg_timeout,
  • (unsigned long)strp);
  • INIT_WORK(&strp->rx_work, strp_rx_work);
  • strp->cb.rcv_msg = cb->rcv_msg;
  • strp->cb.parse_msg = cb->parse_msg;
  • strp->cb.read_sock_done = cb->read_sock_done ? : default_read_sock_done;
  • strp->cb.abort_parser = cb->abort_parser ? : strp_abort_rx_strp;
  • return 0;
  • }

3、tcp callback flows

sk_data_ready -->strp_read_sock -->sock->ops->read_sock(strp->sk, &desc, strp_recv)

  • void strp_data_ready(struct strparser *strp)

  • {

  • if (unlikely(strp->rx_stopped))

  • return;

  • /* This check is needed to synchronize with do_strp_rx_work.

    • do_strp_rx_work acquires a process lock (lock_sock) whereas
    • the lock held here is bh_lock_sock. The two locks can be
    • held by different threads at the same time, but bh_lock_sock
    • allows a thread in BH context to safely check if the process
    • lock is held. In this case, if the lock is held, queue work.
  • */

  • if (sock_owned_by_user(strp->sk)) {

  • queue_work(strp_wq, &strp->rx_work);

  • return;

  • }

  • if (strp->rx_paused)

  • return;

  • if (strp->rx_need_bytes) {

  • if (strp_peek_len(strp) >= strp->rx_need_bytes)

  • strp->rx_need_bytes = 0;

  • else

  • return;

  • }

  • **if (strp_read_sock(strp) == -ENOMEM) **

  • queue_work(strp_wq, &strp->rx_work);

  • }

  • static int strp_read_sock(struct strparser *strp)

  • {

  • struct socket *sock = strp->sk->sk_socket;

  • read_descriptor_t desc;

  • desc.arg.data = strp;

  • desc.error = 0;

  • desc.count = 1; /* give more than one skb per call */

  • /* sk should be locked here, so okay to do read_sock */

  • **sock->ops->read_sock(strp->sk, &desc, strp_recv); **

  • desc.error = strp->cb.read_sock_done(strp, desc.error);

  • return desc.error;

  • }

  • static int strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,

  • unsigned int orig_offset, size_t orig_len)

  • {

  • struct strparser *strp = (struct strparser *)desc->arg.data;

  • return __strp_recv(desc, orig_skb, orig_offset, orig_len,

  • strp->sk->sk_rcvbuf, strp->sk->sk_rcvtimeo);

  • }

  • static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,

  • unsigned int orig_offset, size_t orig_len,

  • size_t max_msg_size, long timeo)

  • {

  • len = (*strp->cb.parse_msg)(strp, head);

  • /* Give skb to upper layer */

  • strp->cb.rcv_msg(strp, head);

  • }

4、timer

static void strp_rx_msg_timeout(unsigned long arg) { struct strparser *strp = (struct strparser *)arg;

/* Message assembly timed out */

STRP_STATS_INCR(strp->stats.rx_msg_timeouts);

lock_sock(strp->sk);

strp->cb.abort_parser(strp, ETIMEDOUT);

release_sock(strp->sk);

}

Clone this wiki locally