Hello netdev mailing list,

I am a PhD student from Germany and currently working on a project that
involves monitoring packets as they are passed from kernel space towards
user space applications. To achieve this, I applied the attached patch
to Kernel v4.4 and implemented the two functions below that are called
from - and with the parameters of - sock_recvmsg() and sock_sendmsg().
For every incoming packet I check if it belongs to the process I want to
monitor. If so, I get the header information as well as the payload and
save the current timestamp. Finally and set the current state to monitor
for the transmission of this packet. Then I compare the payloads of
outgoing packets until a match is found and print the time it took this
packet to travel through the user space.

However, I seem to be unable to get the socket information and data for
incoming packets in __i3_recv_monitor(), as the debug output is always
something like

Dec 19 08:49:51 localhost kernel: [413608.826373] [Packet received]
(13739)0.0.0.0;0;0.0.0.0;0;0;413595528124549
Dec 19 08:49:51 localhost kernel: [413608.831397] [Received data] (null)

Regarding outgoing packets in __i3_send_monitor(), I am at least able to
get the network information from the socket. My data pointer is empty as
well.

Dec 19 09:00:20 localhost kernel: [414238.178057] [Packet send]
(13739)192.168.200.19;36628;192.168.200.20;45110;6;414224859396846
Dec 19 09:00:20 localhost kernel: [414238.181216] [Send data] (null)

The context is that I want to monitor packet processing times of user
space applications that do not alter the payload before retransmitting
packets.

I was hoping that someone with more experience of the network stack
could point me towards what I am missing or doing wrong here.

I hope this is not totally the wrong place to ask such a question and
already thank you in advance!

Best regards,
Stefan

--------------------------------------------------------

void __i3_recv_monitor(struct socket * sock, struct msghdr * msg, size_t
len, int flags) {

  int i = 0;
  const struct iovec * iov;

  if (unlikely(current_state == WAIT_FOR_RECV) && ktime_to_ns(recv_time)
== 0 && current->pid == vnf_pid) {

    recv_time = ktime_get();

    if (unlikely(debug>=2)) printk(KERN_INFO "[Packet received]
(%u)%pI4;%u;%pI4;%d;%d;%lld\n",
                                   current->pid,
                                   &sock->sk->sk_rcv_saddr,
                                   sock->sk->sk_num,
                                   &sock->sk->sk_daddr,
                                   sock->sk->sk_dport,
                                   sock->sk->sk_protocol,
                                   ktime_to_ns(recv_time));

    iov = msg->msg_iter.iov;
    recv_data = (char *)kmalloc(iov->iov_len, GFP_KERNEL);
    copy_from_user(recv_data, iov->iov_base, iov->iov_len);

    printk(KERN_INFO "[Received data] %s\n", *recv_data);

    current_state = WAIT_FOR_SEND;
  }
}


void __i3_send_monitor(struct socket * sock, struct msghdr * msg) {

  int i = 0;
  const struct iovec * iov;

    // I don't like this approach at all... think about something
different!!
  if (unlikely(current_state == WAIT_FOR_SEND) && current->pid == vnf_pid) {

    send_time = ktime_get();

    if (unlikely(debug>=2)) printk(KERN_INFO "[Packet send]
(%u)%pI4;%u;%pI4;%d;%d;%lld\n",
                                   current->pid,
                                   &sock->sk->sk_rcv_saddr,
                                   sock->sk->sk_num,
                                   &sock->sk->sk_daddr,
                                   sock->sk->sk_dport,
                                   sock->sk->sk_protocol,
                                   ktime_to_ns(send_time));


    if (ktime_to_ns(recv_time) != 0) {

      iov = msg->msg_iter.iov;
      send_data = (char *)kmalloc(iov->iov_len, GFP_KERNEL);
      copy_from_user(send_data, iov->iov_base, iov->iov_len);

      printk(KERN_INFO "[Send data] %s\n", *send_data);

      if (unlikely(*recv_data == *send_data)) {
        proc_time = ktime_sub(send_time, recv_time);
        if (unlikely(debug>=2)) printk(KERN_INFO "[Processing time] %lld\n",
ktime_to_ns(proc_time));

        recv_time = ktime_set(0, 0);
        current_state = SLEEP;
        kfree(recv_data);
      }

      kfree(send_data);
    }
  }
}

--------------------------------------------------------

>From 7ef3d1efe53fbfb937e0c1e5200e1a8e40e220e9 Mon Sep 17 00:00:00 2001
From: Stefan Geissler <stefan.geiss...@informatik.uni-wuerzburg.de>
Date: Tue, 14 Nov 2017 12:05:39 +0100
Subject: [PATCH 1/2] Added pointers to hook into socket calls for monitoring
 reasons

---
 net/socket.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/net/socket.c b/net/socket.c
index d730ef9..57ee946 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -113,6 +113,13 @@ unsigned int sysctl_net_busy_read __read_mostly;
 unsigned int sysctl_net_busy_poll __read_mostly;
 #endif

+// Setup pointer to fill with external wrapper functions to monitor sockets
+void (*__i3_send_monitor_ptr)(struct sock *, struct msghdr *);
+void (*__i3_recv_monitor_ptr)(struct sock *, struct msghdr *, size_t ,
int);
+EXPORT_SYMBOL(__i3_send_monitor_ptr);
+EXPORT_SYMBOL(__i3_recv_monitor_ptr);
+
+
 static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
 static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
 static int sock_mmap(struct file *file, struct vm_area_struct *vma);
@@ -615,6 +622,8 @@ static inline int sock_sendmsg_nosec(struct socket
*sock, struct msghdr *msg)

 int sock_sendmsg(struct socket *sock, struct msghdr *msg)
 {
+       if ((unlikely(__i3_send_monitor_ptr))
+         (*__i3_send_monitor_ptr)(sock, msg);
        int err = security_socket_sendmsg(sock, msg,
                                          msg_data_left(msg));

@@ -716,6 +725,8 @@ static inline int sock_recvmsg_nosec(struct socket
*sock, struct msghdr *msg,
 int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
                 int flags)
 {
+       if (unlikely(__i3_recv_monitor_ptr))
+           (*__i3_recv_monitor_ptr)(sock, msg, size, flags);
        int err = security_socket_recvmsg(sock, msg, size, flags);

        return err ?: sock_recvmsg_nosec(sock, msg, size, flags);
@@ -2479,6 +2490,11 @@ EXPORT_SYMBOL(sock_unregister);

 static int __init sock_init(void)
 {
+       // Ensure pointers are set to NULL as long as no module is loaded.
+       // Unsetting the pointers has to be handled by the module upon exit.
+       __i3_recv_monitor_ptr = NULL;
+       __i3_send_monitor_ptr = NULL;
+
        int err;
        /*
         *      Initialize the network sysctl infrastructure.
-- 
2.7.4


>From 262cf38d4c576f6399851e6f5ecbd3a73a62d416 Mon Sep 17 00:00:00 2001
From: Stefan Geissler <stefan.geiss...@informatik.uni-wuerzburg.de>
Date: Tue, 14 Nov 2017 14:04:56 +0100
Subject: [PATCH 2/2] Fixed ISO C90 Warnings

---
 net/socket.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 57ee946..2e840a8 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -114,8 +114,8 @@ unsigned int sysctl_net_busy_poll __read_mostly;
 #endif

 // Setup pointer to fill with external wrapper functions to monitor sockets
-void (*__i3_send_monitor_ptr)(struct sock *, struct msghdr *);
-void (*__i3_recv_monitor_ptr)(struct sock *, struct msghdr *, size_t ,
int);
+void (*__i3_send_monitor_ptr)(struct socket *, struct msghdr *);
+void (*__i3_recv_monitor_ptr)(struct socket *, struct msghdr *, size_t
, int);
 EXPORT_SYMBOL(__i3_send_monitor_ptr);
 EXPORT_SYMBOL(__i3_recv_monitor_ptr);

@@ -622,9 +622,10 @@ static inline int sock_sendmsg_nosec(struct socket
*sock, struct msghdr *msg)

 int sock_sendmsg(struct socket *sock, struct msghdr *msg)
 {
-       if ((unlikely(__i3_send_monitor_ptr))
+       int err;
+       if (unlikely(__i3_send_monitor_ptr))
          (*__i3_send_monitor_ptr)(sock, msg);
-       int err = security_socket_sendmsg(sock, msg,
+       err = security_socket_sendmsg(sock, msg,
                                          msg_data_left(msg));

        return err ?: sock_sendmsg_nosec(sock, msg);
@@ -725,9 +726,10 @@ static inline int sock_recvmsg_nosec(struct socket
*sock, struct msghdr *msg,
 int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
                 int flags)
 {
+       int err;
        if (unlikely(__i3_recv_monitor_ptr))
            (*__i3_recv_monitor_ptr)(sock, msg, size, flags);
-       int err = security_socket_recvmsg(sock, msg, size, flags);
+       err = security_socket_recvmsg(sock, msg, size, flags);

        return err ?: sock_recvmsg_nosec(sock, msg, size, flags);
 }
@@ -2489,13 +2491,14 @@ void sock_unregister(int family)
 EXPORT_SYMBOL(sock_unregister);

 static int __init sock_init(void)
-{
+{
+       int err;
+
        // Ensure pointers are set to NULL as long as no module is loaded.
        // Unsetting the pointers has to be handled by the module upon exit.
        __i3_recv_monitor_ptr = NULL;
        __i3_send_monitor_ptr = NULL;
-
-       int err;
+       
        /*
         *      Initialize the network sysctl infrastructure.
         */
-- 
2.7.4

Reply via email to