[prev in list] [next in list] [prev in thread] [next in thread]
List: openvswitch-dev
Subject: [ovs-dev] [PATCH] stt: linearize for CONFIG_SLUB case
From: pshelar () ovn ! org (Pravin B Shelar)
Date: 2016-03-31 21:30:08
Message-ID: 1459459808-107633-1-git-send-email-pshelar () ovn ! org
[Download RAW message or body]
STT implementation we saw performance improvements with linearizing
skb for SLUB case. So following patch skips zero copy operation
for such a case.
Tested-By: Vasmi Abidi <vabidi at vmware.com>
Signed-off-by: Pravin B Shelar <pshelar at ovn.org>
---
datapath/linux/compat/stt.c | 77 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 71 insertions(+), 6 deletions(-)
diff --git a/datapath/linux/compat/stt.c b/datapath/linux/compat/stt.c
index eb397e8..ae33d5e 100644
--- a/datapath/linux/compat/stt.c
+++ b/datapath/linux/compat/stt.c
@@ -49,6 +49,15 @@
#define STT_DST_PORT 7471
#ifdef OVS_STT
+#ifdef CONFIG_SLUB
+/*
+ * We saw better performance with skipping zero copy in case of SLUB.
+ * So skip zero copy for SLUB case.
+ */
+#define SKIP_ZERO_COPY
+#endif
+
+
#define STT_VER 0
/* @list: Per-net list of STT ports.
@@ -286,6 +295,7 @@ static int straighten_frag_list(struct sk_buff **skbp)
return 0;
}
+#ifndef SKIP_ZERO_COPY
static void copy_skb_metadata(struct sk_buff *to, struct sk_buff *from)
{
to->protocol = from->protocol;
@@ -464,10 +474,14 @@ static int skb_list_segment(struct sk_buff *head, bool ipv4, int l4_offset)
update_headers(head, true, l4_offset, hdr_len, ipv4, 0);
return 0;
}
+#endif
static int coalesce_skb(struct sk_buff **headp)
{
- struct sk_buff *frag, *head, *prev;
+ struct sk_buff *frag, *head;
+#ifndef SKIP_ZERO_COPY
+ struct sk_buff *prev;
+#endif
int err;
err = straighten_frag_list(headp);
@@ -475,6 +489,7 @@ static int coalesce_skb(struct sk_buff **headp)
return err;
head = *headp;
+#ifndef SKIP_ZERO_COPY
/* Coalesce frag list. */
prev = head;
for (frag = head->next; frag; frag = frag->next) {
@@ -500,6 +515,7 @@ static int coalesce_skb(struct sk_buff **headp)
if (!head->next)
return 0;
+#endif
for (frag = head->next; frag; frag = frag->next) {
head->len += frag->len;
head->data_len += frag->len;
@@ -508,9 +524,16 @@ static int coalesce_skb(struct sk_buff **headp)
skb_shinfo(head)->frag_list = head->next;
head->next = NULL;
+#ifdef SKIP_ZERO_COPY
+ if (skb_shinfo(head)->frag_list) {
+ err = __skb_linearize(head);
+ return err;
+ }
+#endif
return 0;
}
+#ifndef SKIP_ZERO_COPY
static int __try_to_segment(struct sk_buff *skb, bool csum_partial,
bool ipv4, bool tcp, int l4_offset)
{
@@ -519,9 +542,16 @@ static int __try_to_segment(struct sk_buff *skb, bool csum_partial,
else
return skb_linearize(skb);
}
+#endif
static int try_to_segment(struct sk_buff *skb)
{
+#ifdef SKIP_ZERO_COPY
+ /* coalesce_skb() since does not generate frag-list no need to
+ * linearize it here.
+ */
+ return 0;
+#else
struct stthdr *stth = stt_hdr(skb);
bool csum_partial = !!(stth->flags & STT_CSUM_PARTIAL);
bool ipv4 = !!(stth->flags & STT_PROTO_IPV4);
@@ -529,11 +559,13 @@ static int try_to_segment(struct sk_buff *skb)
int l4_offset = stth->l4_offset;
return __try_to_segment(skb, csum_partial, ipv4, tcp, l4_offset);
+#endif
}
static int segment_skb(struct sk_buff **headp, bool csum_partial,
bool ipv4, bool tcp, int l4_offset)
{
+#ifndef SKIP_ZERO_COPY
int err;
err = coalesce_skb(headp);
@@ -543,6 +575,7 @@ static int segment_skb(struct sk_buff **headp, bool csum_partial,
if (skb_shinfo(*headp)->frag_list)
return __try_to_segment(*headp, csum_partial,
ipv4, tcp, l4_offset);
+#endif
return 0;
}
@@ -1054,13 +1087,28 @@ static struct pkt_frag *lookup_frag(struct net *net,
return victim_frag;
}
+#ifdef SKIP_ZERO_COPY
+static int __copy_skb(struct sk_buff *to, struct sk_buff *from)
+{
+ if (to->next)
+ return -EINVAL;
+
+ if (unlikely(to->data_len || (from->len > skb_tailroom(to))))
+ return -EINVAL;
+ skb_copy_bits(from, 0, skb_put(to, from->len), from->len);
+ return 0;
+}
+#else
+#define __copy_skb(a, b) -EINVAL;
+#endif
+
static struct sk_buff *reassemble(struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
struct tcphdr *tcph = tcp_hdr(skb);
u32 seq = ntohl(tcph->seq);
struct stt_percpu *stt_percpu;
- struct sk_buff *last_skb;
+ struct sk_buff *last_skb, *copied_skb = NULL;
struct pkt_frag *frag;
struct pkt_key key;
int tot_len;
@@ -1093,6 +1141,15 @@ static struct sk_buff *reassemble(struct sk_buff *skb)
frag = lookup_frag(dev_net(skb->dev), stt_percpu, &key, hash);
if (!frag->skbs) {
+ int err;
+
+ err = pskb_expand_head(skb, skb_headroom(skb),
+ skb->data_len + tot_len, GFP_ATOMIC);
+ if (likely(!err)) {
+ if (unlikely(!__pskb_pull_tail(skb, skb->data_len)))
+ BUG();
+ }
+
frag->skbs = skb;
frag->key = key;
frag->timestamp = jiffies;
@@ -1114,8 +1171,13 @@ static struct sk_buff *reassemble(struct sk_buff *skb)
last_skb = FRAG_CB(frag->skbs)->first.last_skb;
if (likely(FRAG_CB(last_skb)->offset + last_skb->len ==
FRAG_CB(skb)->offset)) {
- last_skb->next = skb;
- FRAG_CB(frag->skbs)->first.last_skb = skb;
+
+ if (!__copy_skb(frag->skbs, skb)) {
+ copied_skb = skb;
+ } else {
+ last_skb->next = skb;
+ FRAG_CB(frag->skbs)->first.last_skb = skb;
+ }
} else {
struct sk_buff *prev = NULL, *next;
@@ -1154,8 +1216,10 @@ static struct sk_buff *reassemble(struct sk_buff *skb)
FRAG_CB(frag->skbs)->first.set_ecn_ce |= INET_ECN_is_ce(iph->tos);
FRAG_CB(frag->skbs)->first.rcvd_len += skb->len;
- FRAG_CB(frag->skbs)->first.mem_used += skb->truesize;
- stt_percpu->frag_mem_used += skb->truesize;
+ if (!copied_skb) {
+ FRAG_CB(frag->skbs)->first.mem_used += skb->truesize;
+ stt_percpu->frag_mem_used += skb->truesize;
+ }
if (FRAG_CB(frag->skbs)->first.tot_len ==
FRAG_CB(frag->skbs)->first.rcvd_len) {
@@ -1174,6 +1238,7 @@ static struct sk_buff *reassemble(struct sk_buff *skb)
skb = NULL;
}
+ kfree_skb(copied_skb);
goto unlock;
unlock_free:
--
1.8.3.1
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic