Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d58572d authored by Subash Abhinov Kasiviswanathan's avatar Subash Abhinov Kasiviswanathan
Browse files

net: rmnet_data: Define the skb recycle handler for transports



rmnet_data currently frees incoming memory when de-aggregating
large incoming aggregated packets. This may introduce additional
overhead in the memory allocator. Add a handler as part of the
rx_handler_data to recycle the skb's. This handler needs to
defined within the specific transport driver. If the recycle
handler is not implemented by the transport, rmnet_data will
free the skb (default behavior).

CRs-Fixed: 1048396
Change-Id: I14b929d78c87ced26cff3c32876d2eec5de33350
Signed-off-by: default avatarSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
parent 9c8924db
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * RMNET Data config definition
 *
 */

#ifndef _RMNET_CONFIG_H_
#define _RMNET_CONFIG_H_

#include <linux/skbuff.h>

struct rmnet_phys_ep_conf_s {
	void (*recycle)(struct sk_buff *); /* Destruct function */
	void *config;
};

#endif /* _RMNET_CONFIG_H_ */
+32 −15
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,7 @@
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/rmnet_data.h>
#include <net/rmnet_config.h>
#include "rmnet_data_config.h"
#include "rmnet_data_handlers.h"
#include "rmnet_data_vnd.h"
@@ -141,14 +142,22 @@ static inline int _rmnet_is_physical_endpoint_associated(struct net_device *dev)
 *     - pointer to configuration if successful
 *     - 0 (null) if device is not associated
 */
static inline struct rmnet_phys_ep_conf_s *_rmnet_get_phys_ep_config
struct rmnet_phys_ep_config *_rmnet_get_phys_ep_config
						(struct net_device *dev)
{
	if (_rmnet_is_physical_endpoint_associated(dev))
		return (struct rmnet_phys_ep_conf_s *)
	struct rmnet_phys_ep_conf_s *_rmnet_phys_ep_config;

	if (_rmnet_is_physical_endpoint_associated(dev)) {
		_rmnet_phys_ep_config = (struct rmnet_phys_ep_conf_s *)
					rcu_dereference(dev->rx_handler_data);
		if (_rmnet_phys_ep_config && _rmnet_phys_ep_config->config)
			return (struct rmnet_phys_ep_config *)
					_rmnet_phys_ep_config->config;
		else
			return 0;
	} else {
		return 0;
	}
}

/**
@@ -165,7 +174,7 @@ static inline struct rmnet_phys_ep_conf_s *_rmnet_get_phys_ep_config
struct rmnet_logical_ep_conf_s *_rmnet_get_logical_ep(struct net_device *dev,
						      int config_id)
{
	struct rmnet_phys_ep_conf_s *config;
	struct rmnet_phys_ep_config *config;
	struct rmnet_logical_ep_conf_s *epconfig_l;

	if (rmnet_vnd_is_vnd(dev))
@@ -400,7 +409,7 @@ static void _rmnet_netlink_get_link_egress_data_format
					 struct rmnet_nl_msg_s *resp_rmnet)
{
	struct net_device *dev;
	struct rmnet_phys_ep_conf_s *config;
	struct rmnet_phys_ep_config *config;
	_RMNET_NETLINK_NULL_CHECKS();
	resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;

@@ -432,7 +441,7 @@ static void _rmnet_netlink_get_link_ingress_data_format
					 struct rmnet_nl_msg_s *resp_rmnet)
{
	struct net_device *dev;
	struct rmnet_phys_ep_conf_s *config;
	struct rmnet_phys_ep_config *config;
	_RMNET_NETLINK_NULL_CHECKS();
	resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;

@@ -725,7 +734,7 @@ int rmnet_set_ingress_data_format(struct net_device *dev,
				  uint32_t ingress_data_format,
				  uint8_t  tail_spacing)
{
	struct rmnet_phys_ep_conf_s *config;
	struct rmnet_phys_ep_config *config;
	ASSERT_RTNL();

	LOGL("(%s,0x%08X);", dev->name, ingress_data_format);
@@ -762,7 +771,7 @@ int rmnet_set_egress_data_format(struct net_device *dev,
				 uint16_t agg_size,
				 uint16_t agg_count)
{
	struct rmnet_phys_ep_conf_s *config;
	struct rmnet_phys_ep_config *config;
	ASSERT_RTNL();

	LOGL("(%s,0x%08X, %d, %d);",
@@ -800,7 +809,9 @@ int rmnet_set_egress_data_format(struct net_device *dev,
int rmnet_associate_network_device(struct net_device *dev)
{
	struct rmnet_phys_ep_conf_s *config;
	struct rmnet_phys_ep_config *conf;
	int rc;

	ASSERT_RTNL();

	LOGL("(%s);\n", dev->name);
@@ -819,19 +830,25 @@ int rmnet_associate_network_device(struct net_device *dev)
	}

	config = kmalloc(sizeof(*config), GFP_ATOMIC);
	conf = kmalloc(sizeof(*conf), GFP_ATOMIC);

	if (!config)
	if (!config || !conf)
		return RMNET_CONFIG_NOMEM;

	memset(config, 0, sizeof(struct rmnet_phys_ep_conf_s));
	config->dev = dev;
	spin_lock_init(&config->agg_lock);
	memset(conf, 0, sizeof(struct rmnet_phys_ep_config));

	config->config = conf;
	conf->dev = dev;
	spin_lock_init(&conf->agg_lock);
	config->recycle = kfree_skb;

	rc = netdev_rx_handler_register(dev, rmnet_rx_handler, config);

	if (rc) {
		LOGM("netdev_rx_handler_register returns %d", rc);
		kfree(config);
		kfree(conf);
		return RMNET_CONFIG_DEVICE_IN_USE;
	}

+5 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/types.h>
#include <linux/time.h>
#include <linux/spinlock.h>
#include <net/rmnet_config.h>

#ifndef _RMNET_DATA_CONFIG_H_
#define _RMNET_DATA_CONFIG_H_
@@ -62,7 +63,7 @@ struct rmnet_logical_ep_conf_s {
 * @agg_time: Wall clock time when aggregated frame was created
 * @agg_last: Last time the aggregation routing was invoked
 */
struct rmnet_phys_ep_conf_s {
struct rmnet_phys_ep_config {
	struct net_device *dev;
	struct rmnet_logical_ep_conf_s local_ep;
	struct rmnet_logical_ep_conf_s muxed_ep[RMNET_DATA_MAX_LOGICAL_EP];
@@ -123,4 +124,7 @@ int rmnet_create_vnd(int id);
int rmnet_create_vnd_prefix(int id, const char *name);
int rmnet_free_vnd(int id);

struct rmnet_phys_ep_config *_rmnet_get_phys_ep_config
						(struct net_device *dev);

#endif /* _RMNET_DATA_CONFIG_H_ */
+9 −10
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/netdev_features.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <net/rmnet_config.h>
#include "rmnet_data_private.h"
#include "rmnet_data_config.h"
#include "rmnet_data_vnd.h"
@@ -321,7 +322,7 @@ static rx_handler_result_t __rmnet_deliver_skb(struct sk_buff *skb,
 *      - RX_HANDLER_PASS if packet should be passed up the stack by caller
 */
static rx_handler_result_t rmnet_ingress_deliver_packet(struct sk_buff *skb,
					    struct rmnet_phys_ep_conf_s *config)
					   struct rmnet_phys_ep_config *config)
{
	if (!config) {
		LOGD("%s", "NULL physical EP provided");
@@ -356,7 +357,7 @@ static rx_handler_result_t rmnet_ingress_deliver_packet(struct sk_buff *skb,
 *      - result of __rmnet_deliver_skb() for all other cases
 */
static rx_handler_result_t _rmnet_map_ingress_handler(struct sk_buff *skb,
					    struct rmnet_phys_ep_conf_s *config)
					   struct rmnet_phys_ep_config *config)
{
	struct rmnet_logical_ep_conf_s *ep;
	uint8_t mux_id;
@@ -440,7 +441,7 @@ static rx_handler_result_t _rmnet_map_ingress_handler(struct sk_buff *skb,
 *      - result of _rmnet_map_ingress_handler() for all other cases
 */
static rx_handler_result_t rmnet_map_ingress_handler(struct sk_buff *skb,
					    struct rmnet_phys_ep_conf_s *config)
					   struct rmnet_phys_ep_config *config)
{
	struct sk_buff *skbn;
	int rc, co = 0;
@@ -480,7 +481,7 @@ static rx_handler_result_t rmnet_map_ingress_handler(struct sk_buff *skb,
 *      - 1 on failure
 */
static int rmnet_map_egress_handler(struct sk_buff *skb,
				    struct rmnet_phys_ep_conf_s *config,
				    struct rmnet_phys_ep_config *config,
				    struct rmnet_logical_ep_conf_s *ep,
				    struct net_device *orig_dev)
{
@@ -563,7 +564,7 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
 */
rx_handler_result_t rmnet_ingress_handler(struct sk_buff *skb)
{
	struct rmnet_phys_ep_conf_s *config;
	struct rmnet_phys_ep_config *config;
	struct net_device *dev;
	int rc;

@@ -574,8 +575,7 @@ rx_handler_result_t rmnet_ingress_handler(struct sk_buff *skb)
	trace_rmnet_ingress_handler(skb);
	rmnet_print_packet(skb, dev->name, 'r');

	config = (struct rmnet_phys_ep_conf_s *)
		rcu_dereference(skb->dev->rx_handler_data);
	config = _rmnet_get_phys_ep_config(skb->dev);

	if (!config) {
		LOGD("%s is not associated with rmnet_data", skb->dev->name);
@@ -654,14 +654,13 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb)
void rmnet_egress_handler(struct sk_buff *skb,
			  struct rmnet_logical_ep_conf_s *ep)
{
	struct rmnet_phys_ep_conf_s *config;
	struct rmnet_phys_ep_config *config;
	struct net_device *orig_dev;
	int rc;
	orig_dev = skb->dev;
	skb->dev = ep->egress_dev;

	config = (struct rmnet_phys_ep_conf_s *)
		rcu_dereference(skb->dev->rx_handler_data);
	config = _rmnet_get_phys_ep_config(skb->dev);

	if (!config) {
		LOGD("%s is not associated with rmnet_data", skb->dev->name);
+12 −3
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,7 @@
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <net/rmnet_config.h>
#include "rmnet_data_private.h"
#include "rmnet_data_stats.h"
#include "rmnet_data_config.h"
@@ -73,9 +74,17 @@ void rmnet_kfree_skb(struct sk_buff *skb, unsigned int reason)
	skb_free[reason]++;
	spin_unlock_irqrestore(&rmnet_skb_free_lock, flags);

	if (skb)
	if (likely(skb)) {
		struct rmnet_phys_ep_conf_s *config;

		config = (struct rmnet_phys_ep_conf_s *)rcu_dereference
			 (skb->dev->rx_handler_data);
		if (likely(config))
			config->recycle(skb);
		else
			kfree_skb(skb);
	}
}

void rmnet_stats_queue_xmit(int rc, unsigned int reason)
{
Loading