[Devel] [PATCH RHEL7 COMMIT] vzprivnet: Split privnet descriptor into 2 parts
Konstantin Khorenko
khorenko at virtuozzo.com
Thu Mar 24 08:53:27 PDT 2016
The commit is pushed to "branch-rh7-3.10.0-327.10.1.vz7.12.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.10.1.vz7.12.3
------>
commit c04981df5c17c82317ef81813c2d57607f611ed9
Author: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Date: Thu Mar 24 19:53:26 2016 +0400
vzprivnet: Split privnet descriptor into 2 parts
Port diff-vz-privnet-split-privnet-into-two-parts
vzprivnet: Split privnet descriptor into 2 parts
The 1st one describes a subnetworks in a network and the 2nd
one describes a rule to match an IP to belong to a net.
Legacy privnets have several subnets per net and have a single
rule to match an IP.
Sparse privnets have a single subnet per net and have several
rules to match.
Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
net/ipv4/netfilter/ip_vzprivnet.c | 103 ++++++++++++++++++++++++--------------
1 file changed, 65 insertions(+), 38 deletions(-)
diff --git a/net/ipv4/netfilter/ip_vzprivnet.c b/net/ipv4/netfilter/ip_vzprivnet.c
index 2c7d532..6d97d8f 100644
--- a/net/ipv4/netfilter/ip_vzprivnet.c
+++ b/net/ipv4/netfilter/ip_vzprivnet.c
@@ -32,11 +32,16 @@
#define VZPRIV_PROCNAME "ip_vzprivnet"
struct vzprivnet {
+ u32 nmask;
+ int weak;
+};
+
+struct vzprivnet_range {
+ struct vzprivnet *pn;
+
/* In big-endian */
u32 netip;
- u32 netmask1;
- u32 netmask2;
- int weak;
+ u32 rmask;
struct rb_node node;
};
@@ -47,25 +52,18 @@ static DEFINE_RWLOCK(vzprivlock);
*/
static struct rb_root rbroot = RB_ROOT;
-static struct vzprivnet vzpriv_internet = {
- .netip = 0,
- .netmask1 = 0,
- .netmask2 = 0,
- .weak = 1
-};
-
/* ip: big-endian IP address */
-static struct vzprivnet *tree_search(u32 ip)
+static struct vzprivnet_range *tree_search(u32 ip)
{
struct rb_node *node = rbroot.rb_node;
ip = ntohl(ip);
while (node) {
- struct vzprivnet *p = rb_entry(node, struct vzprivnet, node);
+ struct vzprivnet_range *p = rb_entry(node, struct vzprivnet_range, node);
u32 start, end;
start = ntohl(p->netip);
- end = start | ~ntohl(p->netmask1);
+ end = start | ~ntohl(p->rmask);
if (ip <= end) {
if (start <= ip)
@@ -75,20 +73,20 @@ static struct vzprivnet *tree_search(u32 ip)
} else
node = node->rb_right;
}
- return &vzpriv_internet;
+ return NULL;
}
-static int tree_insert(struct vzprivnet *data)
+static int tree_insert(struct vzprivnet_range *data)
{
struct rb_node **link = &(rbroot.rb_node), *parent = NULL;
u32 ip = ntohl(data->netip);
while (*link) {
- struct vzprivnet *p = rb_entry(*link, struct vzprivnet, node);
+ struct vzprivnet_range *p = rb_entry(*link, struct vzprivnet_range, node);
u32 start, end;
start = ntohl(p->netip);
- end = start | ~ntohl(p->netmask1);
+ end = start | ~ntohl(p->rmask);
if (start <= ip && ip <= end)
return -EEXIST;
@@ -107,12 +105,12 @@ static int tree_insert(struct vzprivnet *data)
return 0;
}
-static void tree_delete(struct vzprivnet *p)
+static void tree_delete(struct vzprivnet_range *p)
{
rb_erase(&p->node, &rbroot);
}
-static struct vzprivnet *tree_first(void)
+static struct vzprivnet_range *tree_first(void)
{
struct rb_node *node;
@@ -120,10 +118,10 @@ static struct vzprivnet *tree_first(void)
if (!node)
return NULL;
- return rb_entry(node, struct vzprivnet, node);
+ return rb_entry(node, struct vzprivnet_range, node);
}
-static struct vzprivnet *tree_next(struct vzprivnet *p)
+static struct vzprivnet_range *tree_next(struct vzprivnet_range *p)
{
struct rb_node *node;
@@ -131,12 +129,29 @@ static struct vzprivnet *tree_next(struct vzprivnet *p)
if (!node)
return NULL;
- return rb_entry(node, struct vzprivnet, node);
+ return rb_entry(node, struct vzprivnet_range, node);
}
/*
* Generic code
*/
+
+static struct vzprivnet vzpriv_internet = {
+ .nmask = 0,
+ .weak = 1
+};
+
+static struct vzprivnet *vzpriv_search(u32 ip)
+{
+ struct vzprivnet_range *pnr;
+
+ pnr = tree_search(ip);
+ if (pnr != NULL)
+ return pnr->pn;
+ else
+ return &vzpriv_internet;
+}
+
static unsigned int vzprivnet_hook(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
@@ -151,11 +166,11 @@ static unsigned int vzprivnet_hook(const struct nf_hook_ops *ops,
daddr = ip_hdr(skb)->daddr;
read_lock(&vzprivlock);
- p1 = tree_search(saddr);
- p2 = tree_search(daddr);
+ p1 = vzpriv_search(saddr);
+ p2 = vzpriv_search(daddr);
if (p1 == p2) {
- if ((saddr & p1->netmask2) == (daddr & p1->netmask2))
+ if ((saddr & p1->nmask) == (daddr & p1->nmask))
res = NF_ACCEPT;
else
res = NF_DROP;
@@ -197,47 +212,58 @@ static char *nextline(char *s)
static int vzprivnet_add(u32 net, u32 m1, u32 m2, int weak)
{
- struct vzprivnet *p;
+ struct vzprivnet_range *p;
+ struct vzprivnet *pn;
int err;
- p = kmalloc(sizeof(struct vzprivnet), GFP_KERNEL);
+ p = kmalloc(sizeof(struct vzprivnet_range), GFP_KERNEL);
if (!p)
return -ENOMEM;
+ pn = kmalloc(sizeof(struct vzprivnet), GFP_KERNEL);
+ if (!pn) {
+ kfree(p);
+ return -ENOMEM;
+ }
+
+ p->pn = pn;
p->netip = net;
- p->netmask1 = m1;
- p->netmask2 = m2;
- p->weak = weak;
+ p->rmask = m1;
+ pn->nmask = m2;
+ pn->weak = weak;
write_lock_bh(&vzprivlock);
err = tree_insert(p);
write_unlock_bh(&vzprivlock);
- if (err)
+ if (err) {
+ kfree(pn);
kfree(p);
+ }
return err;
}
static int vzprivnet_del(u32 net)
{
- struct vzprivnet *p;
+ struct vzprivnet_range *p;
write_lock_bh(&vzprivlock);
p = tree_search(net);
- if (p == &vzpriv_internet) {
+ if (p == NULL) {
write_unlock_bh(&vzprivlock);
return -ENOENT;
}
tree_delete(p);
write_unlock_bh(&vzprivlock);
+ kfree(p->pn);
kfree(p);
return 0;
}
static void vzprivnet_cleanup(void)
{
- struct vzprivnet *p;
+ struct vzprivnet_range *p;
write_lock_bh(&vzprivlock);
while (1) {
@@ -245,6 +271,7 @@ static void vzprivnet_cleanup(void)
if (!p)
break;
tree_delete(p);
+ kfree(p->pn);
kfree(p);
}
write_unlock_bh(&vzprivlock);
@@ -356,7 +383,7 @@ static void *vzprivnet_seq_start(struct seq_file *seq, loff_t *pos)
read_lock_bh(&vzprivlock);
if (n > 0) {
- struct vzprivnet *p;
+ struct vzprivnet_range *p;
p = tree_first();
while (n-- && p)
@@ -382,11 +409,11 @@ static void vzprivnet_seq_stop(struct seq_file *s, void *v)
static int vzprivnet_seq_show(struct seq_file *s, void *v)
{
- struct vzprivnet *p = v;
+ struct vzprivnet_range *p = v;
seq_printf(s, "%pI4/%u/%u", &p->netip,
- to_prefix(ntohl(p->netmask1)), to_prefix(ntohl(p->netmask2)));
- if (p->weak)
+ to_prefix(ntohl(p->rmask)), to_prefix(ntohl(p->pn->nmask)));
+ if (p->pn->weak)
seq_printf(s, "*\n");
else
seq_printf(s, "\n");
More information about the Devel
mailing list