2017年9月27日 星期三

Namespace : net_generic

include/net/netns/generic.h
/*
 * Generic net pointers are to be used by modules to put some private
 * stuff on the struct net without explicit struct net modification
 *
 * The rules are simple:
 * 1. set pernet_operations->id.  After register_pernet_device you
 *    will have the id of your private pointer.
 * 2. set pernet_operations->size to have the code allocate and free
 *    a private structure pointed to from struct net.
 * 3. do not change this pointer while the net is alive;
 * 4. do not try to have any private reference on the net_generic object.
 *
 * After accomplishing all of the above, the private pointer can be
 * accessed with the net_generic() call.
 */

struct net_generic {
    union {
        struct {
            unsigned int len;
            struct rcu_head rcu;
        } s;

        void *ptr[0];
    };
};

static inline void *net_generic(const struct net *net, unsigned int id)
{
    struct net_generic *ng;
    void *ptr;

    rcu_read_lock();
    ng = rcu_dereference(net->gen);
    ptr = ng->ptr[id];
    rcu_read_unlock();

    return ptr;
}

➠ example
lib/librte_eal/linuxapp/kni/kni_misc.c

static int kni_net_id;

struct kni_net {
    unsigned long device_in_use; /* device in use flag */
    struct mutex kni_kthread_lock;
    struct task_struct *kni_kthread;
    struct rw_semaphore kni_list_lock;
    struct list_head kni_list_head;

};

static struct pernet_operations kni_net_ops = {
    .init = kni_init_net,
    .exit = kni_exit_net,
#ifdef HAVE_SIMPLIFIED_PERNET_OPERATIONS
    .id   = &kni_net_id,
    .size = sizeof(struct kni_net),
#endif

static int __init
kni_init(void)

{
...
    rc = register_pernet_subsys(&kni_net_ops);
...
}

static int
kni_open(struct inode *inode, struct file *file)
{
    struct net *net = current->nsproxy->net_ns;

    struct kni_net *knet = net_generic(net, kni_net_id);
...
}

include/net/net_namespace.h
struct pernet_operations {
    struct list_head list;
    int (*init)(struct net *net);
    void (*exit)(struct net *net);
    void (*exit_batch)(struct list_head *net_exit_list);
    unsigned int *id;
    size_t size;

};

net/core/net_namespace.c
/**
 *      register_pernet_subsys - register a network namespace subsystem
 *  @ops:  pernet operations structure for the subsystem
 *
 *  Register a subsystem which has init and exit functions
 *  that are called when network namespaces are created and
 *  destroyed respectively.
 *
 *  When registered all network namespace init functions are
 *  called for every existing network namespace.  Allowing kernel
 *  modules to have a race free view of the set of network namespaces.
 *
 *  When a new network namespace is created all of the init
 *  methods are called in the order in which they were registered.
 *
 *  When a network namespace is destroyed all of the exit methods
 *  are called in the reverse of the order with which they were
 *  registered.
 */
int register_pernet_subsys(struct pernet_operations *ops)
{
    int error;
    mutex_lock(&net_mutex);
    error =  register_pernet_operations(first_device, ops);
    mutex_unlock(&net_mutex);
    return error;
}

EXPORT_SYMBOL_GPL(register_pernet_subsys);



沒有留言:

張貼留言