18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* ar-skbuff.c: socket buffer destruction handling
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/module.h>
118c2ecf20Sopenharmony_ci#include <linux/net.h>
128c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
138c2ecf20Sopenharmony_ci#include <net/sock.h>
148c2ecf20Sopenharmony_ci#include <net/af_rxrpc.h>
158c2ecf20Sopenharmony_ci#include "ar-internal.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#define is_tx_skb(skb) (rxrpc_skb(skb)->rx_flags & RXRPC_SKB_TX_BUFFER)
188c2ecf20Sopenharmony_ci#define select_skb_count(skb) (is_tx_skb(skb) ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs)
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci/*
218c2ecf20Sopenharmony_ci * Note the allocation or reception of a socket buffer.
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_civoid rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	const void *here = __builtin_return_address(0);
268c2ecf20Sopenharmony_ci	int n = atomic_inc_return(select_skb_count(skb));
278c2ecf20Sopenharmony_ci	trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
288c2ecf20Sopenharmony_ci			rxrpc_skb(skb)->rx_flags, here);
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/*
328c2ecf20Sopenharmony_ci * Note the re-emergence of a socket buffer from a queue or buffer.
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_civoid rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	const void *here = __builtin_return_address(0);
378c2ecf20Sopenharmony_ci	if (skb) {
388c2ecf20Sopenharmony_ci		int n = atomic_read(select_skb_count(skb));
398c2ecf20Sopenharmony_ci		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
408c2ecf20Sopenharmony_ci				rxrpc_skb(skb)->rx_flags, here);
418c2ecf20Sopenharmony_ci	}
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/*
458c2ecf20Sopenharmony_ci * Note the addition of a ref on a socket buffer.
468c2ecf20Sopenharmony_ci */
478c2ecf20Sopenharmony_civoid rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	const void *here = __builtin_return_address(0);
508c2ecf20Sopenharmony_ci	int n = atomic_inc_return(select_skb_count(skb));
518c2ecf20Sopenharmony_ci	trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
528c2ecf20Sopenharmony_ci			rxrpc_skb(skb)->rx_flags, here);
538c2ecf20Sopenharmony_ci	skb_get(skb);
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/*
578c2ecf20Sopenharmony_ci * Note the dropping of a ref on a socket buffer by the core.
588c2ecf20Sopenharmony_ci */
598c2ecf20Sopenharmony_civoid rxrpc_eaten_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	const void *here = __builtin_return_address(0);
628c2ecf20Sopenharmony_ci	int n = atomic_inc_return(&rxrpc_n_rx_skbs);
638c2ecf20Sopenharmony_ci	trace_rxrpc_skb(skb, op, 0, n, 0, here);
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci/*
678c2ecf20Sopenharmony_ci * Note the destruction of a socket buffer.
688c2ecf20Sopenharmony_ci */
698c2ecf20Sopenharmony_civoid rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	const void *here = __builtin_return_address(0);
728c2ecf20Sopenharmony_ci	if (skb) {
738c2ecf20Sopenharmony_ci		int n;
748c2ecf20Sopenharmony_ci		n = atomic_dec_return(select_skb_count(skb));
758c2ecf20Sopenharmony_ci		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
768c2ecf20Sopenharmony_ci				rxrpc_skb(skb)->rx_flags, here);
778c2ecf20Sopenharmony_ci		kfree_skb(skb);
788c2ecf20Sopenharmony_ci	}
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/*
828c2ecf20Sopenharmony_ci * Clear a queue of socket buffers.
838c2ecf20Sopenharmony_ci */
848c2ecf20Sopenharmony_civoid rxrpc_purge_queue(struct sk_buff_head *list)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	const void *here = __builtin_return_address(0);
878c2ecf20Sopenharmony_ci	struct sk_buff *skb;
888c2ecf20Sopenharmony_ci	while ((skb = skb_dequeue((list))) != NULL) {
898c2ecf20Sopenharmony_ci		int n = atomic_dec_return(select_skb_count(skb));
908c2ecf20Sopenharmony_ci		trace_rxrpc_skb(skb, rxrpc_skb_purged,
918c2ecf20Sopenharmony_ci				refcount_read(&skb->users), n,
928c2ecf20Sopenharmony_ci				rxrpc_skb(skb)->rx_flags, here);
938c2ecf20Sopenharmony_ci		kfree_skb(skb);
948c2ecf20Sopenharmony_ci	}
958c2ecf20Sopenharmony_ci}
96