diff options
| -rw-r--r-- | include/linux/netpoll.h | 1 | ||||
| -rw-r--r-- | net/core/netpoll.c | 26 |
2 files changed, 25 insertions, 2 deletions
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index ca5a8733000f..1efe60c5c00c 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h | |||
| @@ -31,6 +31,7 @@ struct netpoll_info { | |||
| 31 | int rx_flags; | 31 | int rx_flags; |
| 32 | spinlock_t rx_lock; | 32 | spinlock_t rx_lock; |
| 33 | struct netpoll *rx_np; /* netpoll that registered an rx_hook */ | 33 | struct netpoll *rx_np; /* netpoll that registered an rx_hook */ |
| 34 | struct sk_buff_head arp_tx; /* list of arp requests to reply to */ | ||
| 34 | }; | 35 | }; |
| 35 | 36 | ||
| 36 | void netpoll_poll(struct netpoll *np); | 37 | void netpoll_poll(struct netpoll *np); |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 377d1e7257b5..471da451cd48 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -54,6 +54,7 @@ static atomic_t trapped; | |||
| 54 | sizeof(struct iphdr) + sizeof(struct ethhdr)) | 54 | sizeof(struct iphdr) + sizeof(struct ethhdr)) |
| 55 | 55 | ||
| 56 | static void zap_completion_queue(void); | 56 | static void zap_completion_queue(void); |
| 57 | static void arp_reply(struct sk_buff *skb); | ||
| 57 | 58 | ||
| 58 | static void queue_process(void *p) | 59 | static void queue_process(void *p) |
| 59 | { | 60 | { |
| @@ -153,6 +154,22 @@ static void poll_napi(struct netpoll *np) | |||
| 153 | } | 154 | } |
| 154 | } | 155 | } |
| 155 | 156 | ||
| 157 | static void service_arp_queue(struct netpoll_info *npi) | ||
| 158 | { | ||
| 159 | struct sk_buff *skb; | ||
| 160 | |||
| 161 | if (unlikely(!npi)) | ||
| 162 | return; | ||
| 163 | |||
| 164 | skb = skb_dequeue(&npi->arp_tx); | ||
| 165 | |||
| 166 | while (skb != NULL) { | ||
| 167 | arp_reply(skb); | ||
| 168 | skb = skb_dequeue(&npi->arp_tx); | ||
| 169 | } | ||
| 170 | return; | ||
| 171 | } | ||
| 172 | |||
| 156 | void netpoll_poll(struct netpoll *np) | 173 | void netpoll_poll(struct netpoll *np) |
| 157 | { | 174 | { |
| 158 | if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller) | 175 | if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller) |
| @@ -163,6 +180,8 @@ void netpoll_poll(struct netpoll *np) | |||
| 163 | if (np->dev->poll) | 180 | if (np->dev->poll) |
| 164 | poll_napi(np); | 181 | poll_napi(np); |
| 165 | 182 | ||
| 183 | service_arp_queue(np->dev->npinfo); | ||
| 184 | |||
| 166 | zap_completion_queue(); | 185 | zap_completion_queue(); |
| 167 | } | 186 | } |
| 168 | 187 | ||
| @@ -442,7 +461,9 @@ int __netpoll_rx(struct sk_buff *skb) | |||
| 442 | int proto, len, ulen; | 461 | int proto, len, ulen; |
| 443 | struct iphdr *iph; | 462 | struct iphdr *iph; |
| 444 | struct udphdr *uh; | 463 | struct udphdr *uh; |
| 445 | struct netpoll *np = skb->dev->npinfo->rx_np; | 464 | struct netpoll_info *npi = skb->dev->npinfo; |
| 465 | struct netpoll *np = npi->rx_np; | ||
| 466 | |||
| 446 | 467 | ||
| 447 | if (!np) | 468 | if (!np) |
| 448 | goto out; | 469 | goto out; |
| @@ -452,7 +473,7 @@ int __netpoll_rx(struct sk_buff *skb) | |||
| 452 | /* check if netpoll clients need ARP */ | 473 | /* check if netpoll clients need ARP */ |
| 453 | if (skb->protocol == __constant_htons(ETH_P_ARP) && | 474 | if (skb->protocol == __constant_htons(ETH_P_ARP) && |
| 454 | atomic_read(&trapped)) { | 475 | atomic_read(&trapped)) { |
| 455 | arp_reply(skb); | 476 | skb_queue_tail(&npi->arp_tx, skb); |
| 456 | return 1; | 477 | return 1; |
| 457 | } | 478 | } |
| 458 | 479 | ||
| @@ -647,6 +668,7 @@ int netpoll_setup(struct netpoll *np) | |||
| 647 | npinfo->poll_owner = -1; | 668 | npinfo->poll_owner = -1; |
| 648 | npinfo->tries = MAX_RETRIES; | 669 | npinfo->tries = MAX_RETRIES; |
| 649 | spin_lock_init(&npinfo->rx_lock); | 670 | spin_lock_init(&npinfo->rx_lock); |
| 671 | skb_queue_head_init(&npinfo->arp_tx); | ||
| 650 | } else | 672 | } else |
| 651 | npinfo = ndev->npinfo; | 673 | npinfo = ndev->npinfo; |
| 652 | 674 | ||
