Hi all,
I meet a crash problem in kernel with openvswitch2.3.0
<4>[1184369.672771] ------------[ cut here ]------------
<2>[1184369.673039] kernel BUG at include/linux/skbuff.h:1219!
<4>[1184369.673304] invalid opcode: 0000 [#1] SMP
<4>[1184369.673573] last sysfs file: /sys/devices/system/cpu/online
<4>[1184369.673838] CPU 2
<4>[1184369.673843] Modules linked in: cls_u32 sch_htb 8021q garp stp llc ipv6
openvswitch libcrc32c iptable_filter ip_tables power_meter hpilo microcode
serio_raw sg shpchp xhci_hcd ixgbe igb dca i2c_algo_bit i2c_core ext4 mbcache
jbd2 sd_mod crc_t10dif ahci dm_mirror dm_region_hash dm_log dm_mod [last
unloaded: scsi_wait_scan]
<4>[1184369.675516]
<4>[1184369.675777] Pid: 0, comm: swapper Tainted: G ---------------
H 2.6.32-279.19.31.el6.ucloud.x86_64 #1 HP ProLiant DL320e Gen8 v2
<4>[1184369.676312] RIP: 0010:[<ffffffffa01dc89d>] [<ffffffffa01dc89d>]
ovs_flow_extract+0x8ed/0xa40 [openvswitch]
<4>[1184369.676843] RSP: 0018:ffff8800456839e0 EFLAGS: 00010283
<4>[1184369.677108] RAX: ffff8807e4f8c46a RBX: ffff880045683a70 RCX:
0000000000000000
<4>[1184369.677630] RDX: 000000000000058d RSI: 0000000000000001 RDI:
ffff880045683af8
<4>[1184369.678152] RBP: ffff880045683a60 R08: 0000000000000400 R09:
000000000000000c
<4>[1184369.678673] R10: ffff8807e4f8c462 R11: 0000000000000000 R12:
ffff8807f8c5c4c0
<4>[1184369.679194] R13: ffffffffa01ea620 R14: ffff8807e4f8c462 R15:
ffff8807e4f8c46a
<4>[1184369.679715] FS: 0000000000000000(0000) GS:ffff880045680000(0000)
knlGS:0000000000000000
<4>[1184369.680233] CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b
<4>[1184369.680495] CR2: 00007f88776d6000 CR3: 00000008263db000 CR4:
00000000001406e0
<4>[1184369.681009] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
0000000000000000
<4>[1184369.681522] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7:
0000000000000400
<4>[1184369.682037] Process swapper (pid: 0, threadinfo ffff880833e76000, task
ffff880833e4a040)
<4>[1184369.682558] Stack:
<4>[1184369.682819] 0000000039000400 ffff88082dbd0118 ffff880045683aa0
ffffffffa01d7b64
<4>[1184369.683092] <d> 0008000002000000 ffff8807e4f8c478 ffff88082dbf8c69
ffffffffa0077d38
<4>[1184369.683627] <d> 0000000000000001 ffff88082edec800 0000000100000000
ffff8807f8c5c4c0
<4>[1184369.684421] Call Trace:
<4>[1184369.684682] <IRQ>
<4>[1184369.685470] [<ffffffffa01d96c4>]
ovs_dp_process_received_packet+0x44/0x80 [openvswitch]
<4>[1184369.685994] [<ffffffffa01e115e>] ovs_vport_receive+0x2e/0x30
[openvswitch]
<4>[1184369.686261] [<ffffffffa01e20cc>] gre_rcv+0xac/0xd0 [openvswitch]
<4>[1184369.686529] [<ffffffffa01e5442>] gre_cisco_rcv+0x1c2/0x310
[openvswitch]
<4>[1184369.686797] [<ffffffffa01e5259>] gre_rcv+0x59/0x80 [openvswitch]
<4>[1184369.687063] [<ffffffff8146197d>] ip_local_deliver_finish+0xdd/0x2d0
<4>[1184369.687331] [<ffffffff81461c08>] ip_local_deliver+0x98/0xa0
<4>[1184369.687596] [<ffffffff814610cd>] ip_rcv_finish+0x12d/0x440
<4>[1184369.687861] [<ffffffff81461655>] ip_rcv+0x275/0x350
<4>[1184369.694516] [<ffffffff8142bc6b>] __netif_receive_skb+0x49b/0x6f0
<4>[1184369.694779] [<ffffffff8142dde8>] netif_receive_skb+0x58/0x60
<4>[1184369.695041] [<ffffffff8142def0>] napi_skb_finish+0x50/0x70
<4>[1184369.695303] [<ffffffff8142ff09>] napi_gro_receive+0x39/0x50
<4>[1184369.695568] [<ffffffffa0148a02>] ixgbe_receive_skb+0x52/0x90 [ixgbe]
<4>[1184369.695832] [<ffffffffa014b485>] ixgbe_poll+0x445/0x1760 [ixgbe]
<4>[1184369.696100] [<ffffffff811043ab>] ? perf_pmu_enable+0x2b/0x40
<4>[1184369.696366] [<ffffffff8110a0b8>] ? perf_event_task_tick+0xa8/0x2f0
<4>[1184369.696631] [<ffffffff81430023>] net_rx_action+0x103/0x2f0
<4>[1184369.696899] [<ffffffff81072911>] __do_softirq+0xc1/0x1e0
<4>[1184369.697165] [<ffffffff810d8ae0>] ? handle_IRQ_event+0x60/0x170
<4>[1184369.697430] [<ffffffff8100c1ec>] call_softirq+0x1c/0x30
<4>[1184369.697694] [<ffffffff8100de85>] do_softirq+0x65/0xa0
<4>[1184369.697956] [<ffffffff810726f5>] irq_exit+0x85/0x90
<4>[1184369.698221] [<ffffffff814f4a25>] do_IRQ+0x75/0xf0
<4>[1184369.698484] [<ffffffff8100b9d3>] ret_from_intr+0x0/0x11
It crashed in ovs_flow_extract with _skb_pull the src&dst mac address
(BUG_ON(skb->len < skb->data_len);)
int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
{
.....
__skb_pull(skb, 2 * ETH_ALEN);
.....
}
I get the skb pointer: It's true len is less than data_len and protocol is
0x2558
crash> struct sk_buff ffff8807f8c5c4c0
struct sk_buff {
next = 0x0,
prev = 0x0,
sk = 0x0,
....
len = 1421,
data_len = 1429,
....
protocol = 22565,
....
transport_header = 98,
network_header = 78,
mac_header = 106,
tail = 110,
end = 640,
head = 0xffff8807e4f8c400 "",
data = 0xffff8807e4f8c46a "RS\001",
truesize = 3328,
users = {
counter = 1
}
}
Get the iphdr, it is a gre packet
crash> struct iphdr ffff8807e4f8c44e
struct iphdr {
ihl = 5 '\005',
version = 4 '\004',
tos = 0 '\000',
tot_len = 46341,
id = 12135,
frag_off = 64,
ttl = 57 '9',
protocol = 47 '/',
check = 30992,
saddr = 1046812588,
daddr = 34020012
}
But I find the gre header get some mess, gre->protocol is not
ETH_P_TEB(0x6558). but 22565 convert to host-edian is 0x2558
I think the packet get some error in the air, But I think ovs should not lead
kernel crash
crash> struct gre_base_hdr ffff8807e4f8c462
struct gre_base_hdr {
flags = 32,
protocol = 22565
}
I think most part of the packet is in the nolinear-spatial.
1. gre_rcv: pskb_may_pull(skb, 12)
pull the 12 bytes to linear-spatial(skb->data). The gre header is 8 bytes with
key.
2. gre_cisco_rcv-->parse_gre_header-->iptunnel_pull_header
{
if (inner_proto == htons(ETH_P_TEB)) {
struct ethhdr *eh;
if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
return -ENOMEM;
....
}
else
skb->protocol = inner_proto;
}
So the wrong inner_proto leads no pull the Mac header to
linear-spatial(skb->data)
3. finally It made a crash in ovs_flow_extract->_pull_skb
I think ovs should check this mess situation in two ways.
1. check the tpi->proto
static int gre_rcv(struct sk_buff *skb,
const struct tnl_ptk_info *tpi)
{
struct ovs_key_ipv4_tunnel tun_key;
struct ovs_net *ovs_net;
struct vport *vport;
__be64 key;
ovs_net = net_generic(dev_net(skb->dev), ovs_net_id);
if ((tpi->flags & TUNNEL_KEY) && (tpi->flags & TUNNEL_SEQ))
vport = rcu_dereference(ovs_net->vport_net.gre64_vport);
else
vport = rcu_dereference(ovs_net->vport_net.gre_vport);
if (unlikely(!vport))
return PACKET_REJECT;
+ if (unlikely(tpi->proto != htons(ETH_P_TEB)))
+ return PACKET_REJECT;
key = key_to_tunnel_id(tpi->key, tpi->seq);
ovs_flow_tun_key_init(&tun_key, ip_hdr(skb), key,
filter_tnl_flags(tpi->flags));
ovs_vport_receive(vport, skb, &tun_key);
return PACKET_RCVD;
}
2. add pskb_may_pull before pull like ip_gre did
int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
{
+ if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
+ return -ENOMEM;
__skb_pull(skb, 2 * ETH_ALEN);
}
_______________________________________________
discuss mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/discuss