[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