[Devel] [PATCH RHEL7 COMMIT] vzprivnet: Cache filtering result on dst
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 c906e9f9ad6687e2a2c0d5f70240b44e66d39cc2
Author: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Date: Thu Mar 24 19:53:27 2016 +0400
vzprivnet: Cache filtering result on dst
changes:
1)make new vzprivnet_hook correspond to nf_hookfn prototype
2)zero-init privnet_mark on dst alloc
Port diff-vz-privnet-cache-filtering-on-dst
vzprivnet: Cache filtering result on dst
This works since the dst is selected by strict src and dst coincidence.
Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
net/core/dst.c | 1 +
net/ipv4/netfilter/ip_vzprivnet.c | 55 ++++++++++++++++++++++++++++++++-------
2 files changed, 46 insertions(+), 10 deletions(-)
diff --git a/net/core/dst.c b/net/core/dst.c
index 3b868bc..e0989e6 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -195,6 +195,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
atomic_set(&dst->__refcnt, initial_ref);
dst->__use = 0;
dst->lastuse = jiffies;
+ dst->privnet_mark = 0;
dst->flags = flags;
dst->pending_confirm = 0;
dst->next = NULL;
diff --git a/net/ipv4/netfilter/ip_vzprivnet.c b/net/ipv4/netfilter/ip_vzprivnet.c
index 6d97d8f..33db6d0 100644
--- a/net/ipv4/netfilter/ip_vzprivnet.c
+++ b/net/ipv4/netfilter/ip_vzprivnet.c
@@ -31,6 +31,23 @@
#define VZPRIV_PROCNAME "ip_vzprivnet"
+enum {
+ VZPRIV_MARK_UNKNOWN,
+ VZPRIV_MARK_ACCEPT,
+ VZPRIV_MARK_DROP,
+ VZPRIV_MARK_MAX
+};
+
+static inline unsigned int dst_pmark_get(struct dst_entry *dst)
+{
+ return dst->privnet_mark;
+}
+
+static inline void dst_pmark_set(struct dst_entry *dst, unsigned int mark)
+{
+ dst->privnet_mark = mark;
+}
+
struct vzprivnet {
u32 nmask;
int weak;
@@ -152,13 +169,9 @@ static struct vzprivnet *vzpriv_search(u32 ip)
return &vzpriv_internet;
}
-static unsigned int vzprivnet_hook(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const struct nf_hook_state *state)
+static noinline unsigned int vzprivnet_classify(struct sk_buff *skb)
{
- int res = NF_ACCEPT;
+ int res;
u32 saddr, daddr;
struct vzprivnet *p1, *p2;
@@ -171,20 +184,42 @@ static unsigned int vzprivnet_hook(const struct nf_hook_ops *ops,
if (p1 == p2) {
if ((saddr & p1->nmask) == (daddr & p1->nmask))
- res = NF_ACCEPT;
+ res = VZPRIV_MARK_ACCEPT;
else
- res = NF_DROP;
+ res = VZPRIV_MARK_DROP;
} else {
if (p1->weak && p2->weak)
- res = NF_ACCEPT;
+ res = VZPRIV_MARK_ACCEPT;
else
- res = NF_DROP;
+ res = VZPRIV_MARK_DROP;
}
read_unlock(&vzprivlock);
return res;
}
+static unsigned int vzprivnet_hook(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_hook_state *state)
+{
+ struct dst_entry *dst;
+ unsigned int pmark = VZPRIV_MARK_UNKNOWN;
+
+ dst = skb_dst(skb);
+ if (dst != NULL)
+ pmark = dst_pmark_get(dst);
+
+ if (unlikely(pmark == VZPRIV_MARK_UNKNOWN)) {
+ pmark = vzprivnet_classify(skb);
+ if (dst != NULL)
+ dst_pmark_set(dst, pmark);
+ }
+
+ return pmark == VZPRIV_MARK_ACCEPT ? NF_ACCEPT : NF_DROP;
+}
+
static struct nf_hook_ops vzprivnet_ops = {
.hook = vzprivnet_hook,
.owner = THIS_MODULE,
More information about the Devel
mailing list