diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 24b9b0210aebbe87624cbc96b22f10d18e1f876d..14ba628b2761a6b9b11e092cd55d395dae617d0f 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -540,24 +540,27 @@ static void ip_list_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb, *next; struct list_head sublist; + INIT_LIST_HEAD(&sublist); list_for_each_entry_safe(skb, next, head, list) { struct dst_entry *dst; + list_del(&skb->list); if (ip_rcv_finish_core(net, sk, skb) == NET_RX_DROP) continue; dst = skb_dst(skb); if (curr_dst != dst) { /* dispatch old sublist */ - list_cut_before(&sublist, head, &skb->list); if (!list_empty(&sublist)) ip_sublist_rcv_finish(&sublist); /* start new sublist */ + INIT_LIST_HEAD(&sublist); curr_dst = dst; } + list_add_tail(&skb->list, &sublist); } /* dispatch final sublist */ - ip_sublist_rcv_finish(head); + ip_sublist_rcv_finish(&sublist); } static void ip_sublist_rcv(struct list_head *head, struct net_device *dev, @@ -577,24 +580,27 @@ void ip_list_rcv(struct list_head *head, struct packet_type *pt, struct sk_buff *skb, *next; struct list_head sublist; + INIT_LIST_HEAD(&sublist); list_for_each_entry_safe(skb, next, head, list) { struct net_device *dev = skb->dev; struct net *net = dev_net(dev); + list_del(&skb->list); skb = ip_rcv_core(skb, net); if (skb == NULL) continue; if (curr_dev != dev || curr_net != net) { /* dispatch old sublist */ - list_cut_before(&sublist, head, &skb->list); if (!list_empty(&sublist)) - ip_sublist_rcv(&sublist, dev, net); + ip_sublist_rcv(&sublist, curr_dev, curr_net); /* start new sublist */ + INIT_LIST_HEAD(&sublist); curr_dev = dev; curr_net = net; } + list_add_tail(&skb->list, &sublist); } /* dispatch final sublist */ - ip_sublist_rcv(head, curr_dev, curr_net); + ip_sublist_rcv(&sublist, curr_dev, curr_net); }