l2tp: fix up inconsistent rx/tx statistics
authorTom Parkin <tparkin@katalix.com>
Fri, 18 Sep 2020 10:23:21 +0000 (11:23 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 18 Sep 2020 21:36:54 +0000 (14:36 -0700)
Historically L2TP core statistics count the L2TP header in the
per-session and per-tunnel byte counts tracked for transmission and
receipt.

Now that l2tp_xmit_skb updates tx stats, it is necessary for
l2tp_xmit_core to pass out the length of the transmitted packet so that
the statistics can be updated correctly.

Signed-off-by: Tom Parkin <tparkin@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/l2tp/l2tp_core.c

index 7de05be..7be5103 100644 (file)
@@ -1006,7 +1006,7 @@ static int l2tp_xmit_queue(struct l2tp_tunnel *tunnel, struct sk_buff *skb, stru
        return err >= 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
 }
 
-static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb)
+static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, unsigned int *len)
 {
        struct l2tp_tunnel *tunnel = session->tunnel;
        unsigned int data_len = skb->len;
@@ -1054,6 +1054,11 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb)
                goto out_unlock;
        }
 
+       /* Report transmitted length before we add encap header, which keeps
+        * statistics consistent for both UDP and IP encap tx/rx paths.
+        */
+       *len = skb->len;
+
        inet = inet_sk(sk);
        switch (tunnel->encap) {
        case L2TP_ENCAPTYPE_UDP:
@@ -1095,10 +1100,10 @@ out_unlock:
  */
 int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb)
 {
-       unsigned int len = skb->len;
+       unsigned int len = 0;
        int ret;
 
-       ret = l2tp_xmit_core(session, skb);
+       ret = l2tp_xmit_core(session, skb, &len);
        if (ret == NET_XMIT_SUCCESS) {
                atomic_long_inc(&session->tunnel->stats.tx_packets);
                atomic_long_add(len, &session->tunnel->stats.tx_bytes);