lkml.org 
[lkml]   [2016]   [Aug]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC V2 PATCH 15/25] net/netpolicy: implement netpolicy register
    Date
    From: Kan Liang <kan.liang@intel.com>

    The socket/task can only be benefited when it register itself with
    specific policy. If it's the first time to register, a record will be
    created and inserted into RCU hash table. The record includes ptr,
    policy and object information. ptr is the socket/task's pointer which is
    used as key to search the record in hash table. Object will be assigned
    later.

    This patch also introduces a new type NET_POLICY_INVALID, which
    indicates that the task/socket are not registered.

    np_hashtable_lock is introduced to protect the hash table.

    Signed-off-by: Kan Liang <kan.liang@intel.com>
    ---
    include/linux/netpolicy.h | 26 ++++++++
    net/core/netpolicy.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++
    2 files changed, 179 insertions(+)

    diff --git a/include/linux/netpolicy.h b/include/linux/netpolicy.h
    index cc75e3c..5900252 100644
    --- a/include/linux/netpolicy.h
    +++ b/include/linux/netpolicy.h
    @@ -17,6 +17,7 @@
    #define __LINUX_NETPOLICY_H

    enum netpolicy_name {
    + NET_POLICY_INVALID = -1,
    NET_POLICY_NONE = 0,
    NET_POLICY_CPU,
    NET_POLICY_BULK,
    @@ -79,12 +80,37 @@ struct netpolicy_info {
    struct list_head obj_list[NETPOLICY_RXTX][NET_POLICY_MAX];
    };

    +struct netpolicy_instance {
    + struct net_device *dev;
    + enum netpolicy_name policy; /* required policy */
    + void *ptr; /* pointers */
    +};
    +
    +/* check if policy is valid */
    +static inline int is_net_policy_valid(enum netpolicy_name policy)
    +{
    + return ((policy < NET_POLICY_MAX) && (policy > NET_POLICY_INVALID));
    +}
    +
    #ifdef CONFIG_NETPOLICY
    extern void update_netpolicy_sys_map(void);
    +extern int netpolicy_register(struct netpolicy_instance *instance,
    + enum netpolicy_name policy);
    +extern void netpolicy_unregister(struct netpolicy_instance *instance);
    #else
    static inline void update_netpolicy_sys_map(void)
    {
    }
    +
    +static inline int netpolicy_register(struct netpolicy_instance *instance,
    + enum netpolicy_name policy)
    +{ return 0;
    +}
    +
    +static inline void netpolicy_unregister(struct netpolicy_instance *instance)
    +{
    +}
    +
    #endif

    #endif /*__LINUX_NETPOLICY_H*/
    diff --git a/net/core/netpolicy.c b/net/core/netpolicy.c
    index 7579685..3605761 100644
    --- a/net/core/netpolicy.c
    +++ b/net/core/netpolicy.c
    @@ -38,6 +38,19 @@
    #include <linux/sort.h>
    #include <linux/ctype.h>
    #include <linux/cpu.h>
    +#include <linux/hashtable.h>
    +
    +struct netpolicy_record {
    + struct hlist_node hash_node;
    + unsigned long ptr_id;
    + enum netpolicy_name policy;
    + struct net_device *dev;
    + struct netpolicy_object *rx_obj;
    + struct netpolicy_object *tx_obj;
    +};
    +
    +static DEFINE_HASHTABLE(np_record_hash, 10);
    +static DEFINE_SPINLOCK(np_hashtable_lock);

    static int netpolicy_get_dev_info(struct net_device *dev,
    struct netpolicy_dev_info *d_info)
    @@ -223,6 +236,143 @@ static int netpolicy_enable(struct net_device *dev)
    return 0;
    }

    +static struct netpolicy_record *netpolicy_record_search(unsigned long ptr_id)
    +{
    + struct netpolicy_record *rec = NULL;
    +
    + hash_for_each_possible_rcu(np_record_hash, rec, hash_node, ptr_id) {
    + if (rec->ptr_id == ptr_id)
    + break;
    + }
    +
    + return rec;
    +}
    +
    +static void put_queue(struct net_device *dev,
    + struct netpolicy_object *rx_obj,
    + struct netpolicy_object *tx_obj)
    +{
    + if (!dev || !dev->netpolicy)
    + return;
    +
    + if (rx_obj)
    + atomic_dec(&rx_obj->refcnt);
    + if (tx_obj)
    + atomic_dec(&tx_obj->refcnt);
    +}
    +
    +static void netpolicy_record_clear_obj(void)
    +{
    + struct netpolicy_record *rec;
    + int i;
    +
    + spin_lock_bh(&np_hashtable_lock);
    + hash_for_each_rcu(np_record_hash, i, rec, hash_node) {
    + put_queue(rec->dev, rec->rx_obj, rec->tx_obj);
    + rec->rx_obj = NULL;
    + rec->tx_obj = NULL;
    + }
    + spin_unlock_bh(&np_hashtable_lock);
    +}
    +
    +static void netpolicy_record_clear_dev_node(struct net_device *dev)
    +{
    + struct netpolicy_record *rec;
    + int i;
    +
    + spin_lock_bh(&np_hashtable_lock);
    + hash_for_each_rcu(np_record_hash, i, rec, hash_node) {
    + if (rec->dev == dev) {
    + hash_del_rcu(&rec->hash_node);
    + kfree(rec);
    + }
    + }
    + spin_unlock_bh(&np_hashtable_lock);
    +}
    +
    +/**
    + * netpolicy_register() - Register per socket/task policy request
    + * @instance: NET policy per socket/task instance info
    + * @policy: request NET policy
    + *
    + * This function intends to register per socket/task policy request.
    + * If it's the first time to register, an record will be created and
    + * inserted into RCU hash table.
    + *
    + * The record includes ptr, policy and object info. ptr of the socket/task
    + * is the key to search the record in hash table. Object will be assigned
    + * until the first packet is received/transmitted.
    + *
    + * Return: 0 on success, others on failure
    + */
    +int netpolicy_register(struct netpolicy_instance *instance,
    + enum netpolicy_name policy)
    +{
    + unsigned long ptr_id = (uintptr_t)instance->ptr;
    + struct netpolicy_record *new, *old;
    +
    + if (!is_net_policy_valid(policy)) {
    + instance->policy = NET_POLICY_INVALID;
    + return -EINVAL;
    + }
    +
    + new = kzalloc(sizeof(*new), GFP_KERNEL);
    + if (!new) {
    + instance->policy = NET_POLICY_INVALID;
    + return -ENOMEM;
    + }
    +
    + spin_lock_bh(&np_hashtable_lock);
    + /* Check it in mapping table */
    + old = netpolicy_record_search(ptr_id);
    + if (old) {
    + if (old->policy != policy) {
    + put_queue(old->dev, old->rx_obj, old->tx_obj);
    + old->rx_obj = NULL;
    + old->tx_obj = NULL;
    + old->policy = policy;
    + }
    + kfree(new);
    + } else {
    + new->ptr_id = ptr_id;
    + new->dev = instance->dev;
    + new->policy = policy;
    + hash_add_rcu(np_record_hash, &new->hash_node, ptr_id);
    + }
    + instance->policy = policy;
    + spin_unlock_bh(&np_hashtable_lock);
    +
    + return 0;
    +}
    +EXPORT_SYMBOL(netpolicy_register);
    +
    +/**
    + * netpolicy_unregister() - Unregister per socket/task policy request
    + * @instance: NET policy per socket/task instance info
    + *
    + * This function intends to unregister policy request by del related record
    + * from hash table.
    + *
    + */
    +void netpolicy_unregister(struct netpolicy_instance *instance)
    +{
    + struct netpolicy_record *record;
    + unsigned long ptr_id = (uintptr_t)instance->ptr;
    +
    + spin_lock_bh(&np_hashtable_lock);
    + /* del from hash table */
    + record = netpolicy_record_search(ptr_id);
    + if (record) {
    + hash_del_rcu(&record->hash_node);
    + /* The record cannot be share. It can be safely free. */
    + put_queue(record->dev, record->rx_obj, record->tx_obj);
    + kfree(record);
    + }
    + instance->policy = NET_POLICY_INVALID;
    + spin_unlock_bh(&np_hashtable_lock);
    +}
    +EXPORT_SYMBOL(netpolicy_unregister);
    +
    const char *policy_name[NET_POLICY_MAX] = {
    "NONE",
    "CPU",
    @@ -825,6 +975,7 @@ static int netpolicy_notify(struct notifier_block *this,
    break;
    case NETDEV_GOING_DOWN:
    uninit_netpolicy(dev);
    + netpolicy_record_clear_dev_node(dev);
    #ifdef CONFIG_PROC_FS
    proc_remove(dev->proc_dev);
    dev->proc_dev = NULL;
    @@ -863,6 +1014,8 @@ void update_netpolicy_sys_map(void)

    dev->netpolicy->cur_policy = NET_POLICY_NONE;

    + /* clear mapping table */
    + netpolicy_record_clear_obj();
    /* rebuild everything */
    netpolicy_disable(dev);
    netpolicy_enable(dev);
    --
    2.5.5
    \
     
     \ /
      Last update: 2016-08-04 22:21    [W:2.696 / U:0.280 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site