From f97ee16ac05a2c81b4b2f7b9d39dc7b93de3393b Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Tue, 23 Sep 2014 15:15:37 -0700 Subject: [PATCH] datapath: Restore OVS_CB after skb_segment. OVS needs to segments large skb before sending it for miss packet handling to userspace. but skb_gso_segment uses skb->cb. This corrupted OVS_CB which result in following panic. [ 735.419921] BUG: unable to handle kernel paging request at 00000014000001b2 [ 735.423168] Oops: 0000 [#1] SMP DEBUG_PAGEALLOC [ 735.445097] RIP: 0010:[] [] ovs_nla_put_flow+0x37/0x7c0 [openvswitch] [ 735.468858] Call Trace: [ 735.470384] [] queue_userspace_packet+0x332/0x4d0 [openvswitch] [ 735.471741] [] queue_gso_packets+0xf5/0x180 [openvswitch] [ 735.481862] [] ovs_dp_upcall+0x65/0x70 [openvswitch] [ 735.483031] [] ovs_dp_process_packet+0x181/0x1b0 [openvswitch] [ 735.484391] [] ovs_vport_receive+0x65/0x90 [openvswitch] [ 735.492638] [] internal_dev_xmit+0x68/0x110 [openvswitch] [ 735.495334] [] dev_hard_start_xmit+0x2e6/0x8b0 [ 735.496503] [] __dev_queue_xmit+0x3c7/0x920 [ 735.499827] [] dev_queue_xmit+0x10/0x20 [ 735.500798] [] ip_finish_output+0x6a0/0x950 [ 735.502818] [] ip_output+0x68/0x110 [ 735.503835] [] ip_local_out+0x29/0x90 [ 735.504801] [] ip_queue_xmit+0x1d6/0x640 [ 735.507015] [] tcp_transmit_skb+0x477/0xac0 [ 735.508260] [] tcp_write_xmit+0x136/0xba0 [ 735.510829] [] __tcp_push_pending_frames+0x2e/0xc0 [ 735.512296] [] tcp_sendmsg+0xa63/0xd50 [ 735.513526] [] inet_sendmsg+0x10c/0x220 [ 735.516025] [] sock_sendmsg+0x9c/0xe0 [ 735.518066] [] SYSC_sendto+0x121/0x1c0 [ 735.521398] [] SyS_sendto+0xe/0x10 [ 735.522473] [] system_call_fastpath+0x16/0x1b Reported-by: Andy Zhou Signed-off-by: Pravin B Shelar Acked-by: Andy Zhou --- datapath/datapath.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/datapath/datapath.c b/datapath/datapath.c index 481b923e3..95ba520a0 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -339,15 +339,19 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, struct dp_upcall_info later_info; struct sw_flow_key later_key; struct sk_buff *segs, *nskb; + struct ovs_skb_cb ovs_cb; int err; + ovs_cb = *OVS_CB(skb); segs = __skb_gso_segment(skb, NETIF_F_SG, false); + *OVS_CB(skb) = ovs_cb; if (IS_ERR(segs)) return PTR_ERR(segs); /* Queue all of the segments. */ skb = segs; do { + *OVS_CB(skb) = ovs_cb; err = queue_userspace_packet(dp, skb, upcall_info); if (err) break; -- 2.20.1