File Index
Files and directories
Sign in
FILE

ip_vs_pe.c

File preview with syntax highlighting.

linux-6.19.14/net/netfilter/ipvs/ip_vs_pe.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2#define pr_fmt(fmt) "IPVS: " fmt
  3
  4#include <linux/module.h>
  5#include <linux/spinlock.h>
  6#include <linux/interrupt.h>
  7#include <asm/string.h>
  8#include <linux/kmod.h>
  9#include <linux/sysctl.h>
 10
 11#include <net/ip_vs.h>
 12
 13/* IPVS pe list */
 14static LIST_HEAD(ip_vs_pe);
 15
 16/* semaphore for IPVS PEs. */
 17static DEFINE_MUTEX(ip_vs_pe_mutex);
 18
 19/* Get pe in the pe list by name */
 20struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name)
 21{
 22	struct ip_vs_pe *pe;
 23
 24	IP_VS_DBG(10, "%s(): pe_name \"%s\"\n", __func__,
 25		  pe_name);
 26
 27	rcu_read_lock();
 28	list_for_each_entry_rcu(pe, &ip_vs_pe, n_list) {
 29		/* Test and get the modules atomically */
 30		if (pe->module &&
 31		    !try_module_get(pe->module)) {
 32			/* This pe is just deleted */
 33			continue;
 34		}
 35		if (strcmp(pe_name, pe->name)==0) {
 36			/* HIT */
 37			rcu_read_unlock();
 38			return pe;
 39		}
 40		module_put(pe->module);
 41	}
 42	rcu_read_unlock();
 43
 44	return NULL;
 45}
 46
 47/* Lookup pe and try to load it if it doesn't exist */
 48struct ip_vs_pe *ip_vs_pe_getbyname(const char *name)
 49{
 50	struct ip_vs_pe *pe;
 51
 52	/* Search for the pe by name */
 53	pe = __ip_vs_pe_getbyname(name);
 54
 55	/* If pe not found, load the module and search again */
 56	if (!pe) {
 57		request_module("ip_vs_pe_%s", name);
 58		pe = __ip_vs_pe_getbyname(name);
 59	}
 60
 61	return pe;
 62}
 63
 64/* Register a pe in the pe list */
 65int register_ip_vs_pe(struct ip_vs_pe *pe)
 66{
 67	struct ip_vs_pe *tmp;
 68
 69	/* increase the module use count */
 70	if (!ip_vs_use_count_inc())
 71		return -ENOENT;
 72
 73	mutex_lock(&ip_vs_pe_mutex);
 74	/* Make sure that the pe with this name doesn't exist
 75	 * in the pe list.
 76	 */
 77	list_for_each_entry(tmp, &ip_vs_pe, n_list) {
 78		if (strcmp(tmp->name, pe->name) == 0) {
 79			mutex_unlock(&ip_vs_pe_mutex);
 80			ip_vs_use_count_dec();
 81			pr_err("%s(): [%s] pe already existed "
 82			       "in the system\n", __func__, pe->name);
 83			return -EINVAL;
 84		}
 85	}
 86	/* Add it into the d-linked pe list */
 87	list_add_rcu(&pe->n_list, &ip_vs_pe);
 88	mutex_unlock(&ip_vs_pe_mutex);
 89
 90	pr_info("[%s] pe registered.\n", pe->name);
 91
 92	return 0;
 93}
 94EXPORT_SYMBOL_GPL(register_ip_vs_pe);
 95
 96/* Unregister a pe from the pe list */
 97int unregister_ip_vs_pe(struct ip_vs_pe *pe)
 98{
 99	mutex_lock(&ip_vs_pe_mutex);
100	/* Remove it from the d-linked pe list */
101	list_del_rcu(&pe->n_list);
102	mutex_unlock(&ip_vs_pe_mutex);
103
104	/* decrease the module use count */
105	ip_vs_use_count_dec();
106
107	pr_info("[%s] pe unregistered.\n", pe->name);
108
109	return 0;
110}
111EXPORT_SYMBOL_GPL(unregister_ip_vs_pe);
~/ Read-only file preview.