diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 9c28cec1a083..f8db7064d81c 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -698,6 +698,10 @@ static void prb_retire_rx_blk_timer_expired(unsigned long data) | |||
698 | 698 | ||
699 | if (pkc->last_kactive_blk_num == pkc->kactive_blk_num) { | 699 | if (pkc->last_kactive_blk_num == pkc->kactive_blk_num) { |
700 | if (!frozen) { | 700 | if (!frozen) { |
701 | if (!BLOCK_NUM_PKTS(pbd)) { | ||
702 | /* An empty block. Just refresh the timer. */ | ||
703 | goto refresh_timer; | ||
704 | } | ||
701 | prb_retire_current_block(pkc, po, TP_STATUS_BLK_TMO); | 705 | prb_retire_current_block(pkc, po, TP_STATUS_BLK_TMO); |
702 | if (!prb_dispatch_next_block(pkc, po)) | 706 | if (!prb_dispatch_next_block(pkc, po)) |
703 | goto refresh_timer; | 707 | goto refresh_timer; |
@@ -798,7 +802,11 @@ static void prb_close_block(struct tpacket_kbdq_core *pkc1, | |||
798 | h1->ts_last_pkt.ts_sec = last_pkt->tp_sec; | 802 | h1->ts_last_pkt.ts_sec = last_pkt->tp_sec; |
799 | h1->ts_last_pkt.ts_nsec = last_pkt->tp_nsec; | 803 | h1->ts_last_pkt.ts_nsec = last_pkt->tp_nsec; |
800 | } else { | 804 | } else { |
801 | /* Ok, we tmo'd - so get the current time */ | 805 | /* Ok, we tmo'd - so get the current time. |
806 | * | ||
807 | * It shouldn't really happen as we don't close empty | ||
808 | * blocks. See prb_retire_rx_blk_timer_expired(). | ||
809 | */ | ||
802 | struct timespec ts; | 810 | struct timespec ts; |
803 | getnstimeofday(&ts); | 811 | getnstimeofday(&ts); |
804 | h1->ts_last_pkt.ts_sec = ts.tv_sec; | 812 | h1->ts_last_pkt.ts_sec = ts.tv_sec; |
@@ -1349,14 +1357,14 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev, | |||
1349 | return 0; | 1357 | return 0; |
1350 | } | 1358 | } |
1351 | 1359 | ||
1360 | if (fanout_has_flag(f, PACKET_FANOUT_FLAG_DEFRAG)) { | ||
1361 | skb = ip_check_defrag(skb, IP_DEFRAG_AF_PACKET); | ||
1362 | if (!skb) | ||
1363 | return 0; | ||
1364 | } | ||
1352 | switch (f->type) { | 1365 | switch (f->type) { |
1353 | case PACKET_FANOUT_HASH: | 1366 | case PACKET_FANOUT_HASH: |
1354 | default: | 1367 | default: |
1355 | if (fanout_has_flag(f, PACKET_FANOUT_FLAG_DEFRAG)) { | ||
1356 | skb = ip_check_defrag(skb, IP_DEFRAG_AF_PACKET); | ||
1357 | if (!skb) | ||
1358 | return 0; | ||
1359 | } | ||
1360 | idx = fanout_demux_hash(f, skb, num); | 1368 | idx = fanout_demux_hash(f, skb, num); |
1361 | break; | 1369 | break; |
1362 | case PACKET_FANOUT_LB: | 1370 | case PACKET_FANOUT_LB: |
@@ -3115,11 +3123,18 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, | |||
3115 | return 0; | 3123 | return 0; |
3116 | } | 3124 | } |
3117 | 3125 | ||
3118 | static void packet_dev_mclist(struct net_device *dev, struct packet_mclist *i, int what) | 3126 | static void packet_dev_mclist_delete(struct net_device *dev, |
3127 | struct packet_mclist **mlp) | ||
3119 | { | 3128 | { |
3120 | for ( ; i; i = i->next) { | 3129 | struct packet_mclist *ml; |
3121 | if (i->ifindex == dev->ifindex) | 3130 | |
3122 | packet_dev_mc(dev, i, what); | 3131 | while ((ml = *mlp) != NULL) { |
3132 | if (ml->ifindex == dev->ifindex) { | ||
3133 | packet_dev_mc(dev, ml, -1); | ||
3134 | *mlp = ml->next; | ||
3135 | kfree(ml); | ||
3136 | } else | ||
3137 | mlp = &ml->next; | ||
3123 | } | 3138 | } |
3124 | } | 3139 | } |
3125 | 3140 | ||
@@ -3196,12 +3211,11 @@ static int packet_mc_drop(struct sock *sk, struct packet_mreq_max *mreq) | |||
3196 | packet_dev_mc(dev, ml, -1); | 3211 | packet_dev_mc(dev, ml, -1); |
3197 | kfree(ml); | 3212 | kfree(ml); |
3198 | } | 3213 | } |
3199 | rtnl_unlock(); | 3214 | break; |
3200 | return 0; | ||
3201 | } | 3215 | } |
3202 | } | 3216 | } |
3203 | rtnl_unlock(); | 3217 | rtnl_unlock(); |
3204 | return -EADDRNOTAVAIL; | 3218 | return 0; |
3205 | } | 3219 | } |
3206 | 3220 | ||
3207 | static void packet_flush_mclist(struct sock *sk) | 3221 | static void packet_flush_mclist(struct sock *sk) |
@@ -3551,7 +3565,7 @@ static int packet_notifier(struct notifier_block *this, | |||
3551 | switch (msg) { | 3565 | switch (msg) { |
3552 | case NETDEV_UNREGISTER: | 3566 | case NETDEV_UNREGISTER: |
3553 | if (po->mclist) | 3567 | if (po->mclist) |
3554 | packet_dev_mclist(dev, po->mclist, -1); | 3568 | packet_dev_mclist_delete(dev, &po->mclist); |
3555 | /* fallthrough */ | 3569 | /* fallthrough */ |
3556 | 3570 | ||
3557 | case NETDEV_DOWN: | 3571 | case NETDEV_DOWN: |