summaryrefslogtreecommitdiff
path: root/datapath
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2015-12-10 14:19:56 -0800
committerPravin B Shelar <pshelar@nicira.com>2015-12-10 20:34:00 -0800
commit68fc34515178c20391864b3b9886f93716bdfd5c (patch)
tree439e835d1cf79fc363a6737e14fe19ed22300dcb /datapath
parentd05293afdd47b27e672a578705ed7d53db29d04a (diff)
downloadopenvswitch-68fc34515178c20391864b3b9886f93716bdfd5c.tar.gz
datapath: Fix STT packet receive handling.
STT reassembly can generate list of packets. But it was handled as a single skb. Following patch fixes it. Fixes: e23775f20 ("datapath: Add support for lwtunnel"). Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Acked-by: Jesse Gross <jesse@kernel.org> Acked-by: Joe Stringer <joe@ovn.org>
Diffstat (limited to 'datapath')
-rw-r--r--datapath/linux/compat/stt.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/datapath/linux/compat/stt.c b/datapath/linux/compat/stt.c
index 107aa2bb2..80649802f 100644
--- a/datapath/linux/compat/stt.c
+++ b/datapath/linux/compat/stt.c
@@ -1286,8 +1286,24 @@ static bool set_offloads(struct sk_buff *skb)
return true;
}
+static void rcv_list(struct net_device *dev, struct sk_buff *skb,
+ struct metadata_dst *tun_dst)
+{
+ struct sk_buff *next;
+
+ do {
+ next = skb->next;
+ skb->next = NULL;
+ if (next) {
+ ovs_dst_hold((struct dst_entry *)tun_dst);
+ ovs_skb_dst_set(next, (struct dst_entry *)tun_dst);
+ }
+ ovs_ip_tunnel_rcv(dev, skb, tun_dst);
+ } while ((skb = next));
+}
+
#ifndef HAVE_METADATA_DST
-static int __rcv(struct stt_dev *stt_dev, struct sk_buff *skb)
+static int __stt_rcv(struct stt_dev *stt_dev, struct sk_buff *skb)
{
struct metadata_dst tun_dst;
@@ -1296,11 +1312,11 @@ static int __rcv(struct stt_dev *stt_dev, struct sk_buff *skb)
tun_dst.u.tun_info.key.tp_src = tcp_hdr(skb)->source;
tun_dst.u.tun_info.key.tp_dst = tcp_hdr(skb)->dest;
- ovs_ip_tunnel_rcv(stt_dev->dev, skb, &tun_dst);
+ rcv_list(stt_dev->dev, skb, &tun_dst);
return 0;
}
#else
-static int __rcv(struct stt_dev *stt_dev, struct sk_buff *skb)
+static int __stt_rcv(struct stt_dev *stt_dev, struct sk_buff *skb)
{
struct metadata_dst *tun_dst;
__be16 flags;
@@ -1314,11 +1330,11 @@ static int __rcv(struct stt_dev *stt_dev, struct sk_buff *skb)
tun_dst->u.tun_info.key.tp_src = tcp_hdr(skb)->source;
tun_dst->u.tun_info.key.tp_dst = tcp_hdr(skb)->dest;
- ovs_ip_tunnel_rcv(stt_dev->dev, skb, tun_dst);
+ rcv_list(stt_dev->dev, skb, tun_dst);
return 0;
}
-
#endif
+
static void stt_rcv(struct stt_dev *stt_dev, struct sk_buff *skb)
{
int err;
@@ -1348,7 +1364,7 @@ static void stt_rcv(struct stt_dev *stt_dev, struct sk_buff *skb)
if (skb_shinfo(skb)->frag_list && try_to_segment(skb))
goto drop;
- err = __rcv(stt_dev, skb);
+ err = __stt_rcv(stt_dev, skb);
if (err)
goto drop;
return;