[Devel] [PATCH rh7 1/2] ms/ipv6: Provide ipv6 version of "disable_policy" sysctl
Vasily Averin
vvs at virtuozzo.com
Fri Nov 26 11:02:09 MSK 2021
From: David Forster <dforster at brocade.com>
This provides equivalent functionality to the existing ipv4
"disable_policy" systcl. ie. Allows IPsec processing to be skipped
on terminating packets on a per-interface basis.
Signed-off-by: David Forster <dforster at brocade.com>
Signed-off-by: David S. Miller <davem at davemloft.net>
(cherry picked from commit df789fe752065f2ce761ba434125e335b514899f)
[VvS: minor context changes]
https://pmc.acronis.com/browse/VSTOR-48427
Signed-off-by: Vasily Averin <vvs at virtuozzo.com>
---
include/linux/ipv6.h | 1 +
include/uapi/linux/ipv6.h | 1 +
net/ipv6/addrconf.c | 114 ++++++++++++++++++++++++++++++++++++++
3 files changed, 116 insertions(+)
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 452fc5f05389..a12411cc1865 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -60,6 +60,7 @@ struct ipv6_devconf {
__s32 keep_addr_on_down;
__u32 enhanced_dad;
#endif
+ __s32 disable_policy;
void *sysctl;
};
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index c3a0ebc7cd2d..91f279041f5a 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -177,6 +177,7 @@ enum {
__RH_RESERVED_DEVCONF_SEG6_ENABLED,
__RH_RESERVED_DEVCONF_SEG6_REQUIRE_HMAC,
DEVCONF_ENHANCED_DAD,
+ DEVCONF_DISABLE_POLICY,
DEVCONF_MAX
};
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 70843d203de9..f6a9c23c192f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -213,6 +213,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
},
.keep_addr_on_down = 0,
.enhanced_dad = 1,
+ .disable_policy = 0,
};
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -253,6 +254,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
},
.keep_addr_on_down = 0,
.enhanced_dad = 1,
+ .disable_policy = 0,
};
/* Check if link is ready: is it up and is a valid qdisc available */
@@ -837,6 +839,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
bool can_block)
{
gfp_t gfp_flags = can_block ? GFP_KERNEL : GFP_ATOMIC;
+ struct net *net = dev_net(idev->dev);
struct inet6_ifaddr *ifa = NULL;
struct rt6_info *rt = NULL;
int err = 0;
@@ -887,6 +890,10 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
goto out;
}
+ if (net->ipv6.devconf_all->disable_policy ||
+ idev->cnf.disable_policy)
+ rt->dst.flags |= DST_NOPOLICY;
+
neigh_parms_data_state_setall(idev->nd_parms);
ifa->addr = *addr;
@@ -4881,6 +4888,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
/* we omit DEVCONF_STABLE_SECRET for now */
array[DEVCONF_KEEP_ADDR_ON_DOWN] = cnf->keep_addr_on_down;
array[DEVCONF_ENHANCED_DAD] = cnf->enhanced_dad;
+ array[DEVCONF_DISABLE_POLICY] = cnf->disable_policy;
}
static inline size_t inet6_ifla6_size(void)
@@ -5582,6 +5590,105 @@ static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write,
return err;
}
+static
+void addrconf_set_nopolicy(struct rt6_info *rt, int action)
+{
+ if (rt) {
+ if (action)
+ rt->dst.flags |= DST_NOPOLICY;
+ else
+ rt->dst.flags &= ~DST_NOPOLICY;
+ }
+}
+
+static
+void addrconf_disable_policy_idev(struct inet6_dev *idev, int val)
+{
+ struct inet6_ifaddr *ifa;
+
+ read_lock_bh(&idev->lock);
+ list_for_each_entry(ifa, &idev->addr_list, if_list) {
+ spin_lock(&ifa->lock);
+ if (ifa->rt) {
+ struct rt6_info *rt = ifa->rt;
+ struct fib6_table *table = rt->rt6i_table;
+ int cpu;
+
+ read_lock(&table->tb6_lock);
+ addrconf_set_nopolicy(ifa->rt, val);
+ if (rt->rt6i_pcpu) {
+ for_each_possible_cpu(cpu) {
+ struct rt6_info **rtp;
+
+ rtp = per_cpu_ptr(rt->rt6i_pcpu, cpu);
+ addrconf_set_nopolicy(*rtp, val);
+ }
+ }
+ read_unlock(&table->tb6_lock);
+ }
+ spin_unlock(&ifa->lock);
+ }
+ read_unlock_bh(&idev->lock);
+}
+
+static
+int addrconf_disable_policy(struct ctl_table *ctl, int *valp, int val)
+{
+ struct inet6_dev *idev;
+ struct net *net;
+
+ if (!rtnl_trylock())
+ return restart_syscall();
+
+ *valp = val;
+
+ net = (struct net *)ctl->extra2;
+ if (valp == &net->ipv6.devconf_dflt->disable_policy) {
+ rtnl_unlock();
+ return 0;
+ }
+
+ if (valp == &net->ipv6.devconf_all->disable_policy) {
+ struct net_device *dev;
+
+ for_each_netdev(net, dev) {
+ idev = __in6_dev_get(dev);
+ if (idev)
+ addrconf_disable_policy_idev(idev, val);
+ }
+ } else {
+ idev = (struct inet6_dev *)ctl->extra1;
+ addrconf_disable_policy_idev(idev, val);
+ }
+
+ rtnl_unlock();
+ return 0;
+}
+
+static
+int addrconf_sysctl_disable_policy(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ int *valp = ctl->data;
+ int val = *valp;
+ loff_t pos = *ppos;
+ struct ctl_table lctl;
+ int ret;
+
+ lctl = *ctl;
+ lctl.data = &val;
+ ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
+
+ if (write && (*valp != val))
+ ret = addrconf_disable_policy(ctl, valp, val);
+
+ if (ret)
+ *ppos = pos;
+
+ return ret;
+}
+
static struct addrconf_sysctl_table
{
struct ctl_table_header *sysctl_header;
@@ -5854,6 +5961,13 @@ static struct addrconf_sysctl_table
.mode = 0644,
.proc_handler = proc_dointvec,
},
+ {
+ .procname = "disable_policy",
+ .data = &ipv6_devconf.disable_policy,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = addrconf_sysctl_disable_policy,
+ },
{
/* sentinel */
}
--
2.25.1
More information about the Devel
mailing list