diff options
Diffstat (limited to 'net/core/netpoll.c')
| -rw-r--r-- | net/core/netpoll.c | 178 |
1 files changed, 112 insertions, 66 deletions
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 0b4d0d35ef40..6f9206b36dc2 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -407,11 +407,24 @@ static void arp_reply(struct sk_buff *skb) | |||
| 407 | __be32 sip, tip; | 407 | __be32 sip, tip; |
| 408 | unsigned char *sha; | 408 | unsigned char *sha; |
| 409 | struct sk_buff *send_skb; | 409 | struct sk_buff *send_skb; |
| 410 | struct netpoll *np = NULL; | 410 | struct netpoll *np, *tmp; |
| 411 | unsigned long flags; | ||
| 412 | int hits = 0; | ||
| 413 | |||
| 414 | if (list_empty(&npinfo->rx_np)) | ||
| 415 | return; | ||
| 416 | |||
| 417 | /* Before checking the packet, we do some early | ||
| 418 | inspection whether this is interesting at all */ | ||
| 419 | spin_lock_irqsave(&npinfo->rx_lock, flags); | ||
| 420 | list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { | ||
| 421 | if (np->dev == skb->dev) | ||
| 422 | hits++; | ||
| 423 | } | ||
| 424 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | ||
| 411 | 425 | ||
| 412 | if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev) | 426 | /* No netpoll struct is using this dev */ |
| 413 | np = npinfo->rx_np; | 427 | if (!hits) |
| 414 | if (!np) | ||
| 415 | return; | 428 | return; |
| 416 | 429 | ||
| 417 | /* No arp on this interface */ | 430 | /* No arp on this interface */ |
| @@ -437,77 +450,91 @@ static void arp_reply(struct sk_buff *skb) | |||
| 437 | arp_ptr += skb->dev->addr_len; | 450 | arp_ptr += skb->dev->addr_len; |
| 438 | memcpy(&sip, arp_ptr, 4); | 451 | memcpy(&sip, arp_ptr, 4); |
| 439 | arp_ptr += 4; | 452 | arp_ptr += 4; |
| 440 | /* if we actually cared about dst hw addr, it would get copied here */ | 453 | /* If we actually cared about dst hw addr, |
| 454 | it would get copied here */ | ||
| 441 | arp_ptr += skb->dev->addr_len; | 455 | arp_ptr += skb->dev->addr_len; |
| 442 | memcpy(&tip, arp_ptr, 4); | 456 | memcpy(&tip, arp_ptr, 4); |
| 443 | 457 | ||
| 444 | /* Should we ignore arp? */ | 458 | /* Should we ignore arp? */ |
| 445 | if (tip != np->local_ip || | 459 | if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) |
| 446 | ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) | ||
| 447 | return; | 460 | return; |
| 448 | 461 | ||
| 449 | size = arp_hdr_len(skb->dev); | 462 | size = arp_hdr_len(skb->dev); |
| 450 | send_skb = find_skb(np, size + LL_ALLOCATED_SPACE(np->dev), | ||
| 451 | LL_RESERVED_SPACE(np->dev)); | ||
| 452 | 463 | ||
| 453 | if (!send_skb) | 464 | spin_lock_irqsave(&npinfo->rx_lock, flags); |
| 454 | return; | 465 | list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { |
| 455 | 466 | if (tip != np->local_ip) | |
| 456 | skb_reset_network_header(send_skb); | 467 | continue; |
| 457 | arp = (struct arphdr *) skb_put(send_skb, size); | ||
| 458 | send_skb->dev = skb->dev; | ||
| 459 | send_skb->protocol = htons(ETH_P_ARP); | ||
| 460 | 468 | ||
| 461 | /* Fill the device header for the ARP frame */ | 469 | send_skb = find_skb(np, size + LL_ALLOCATED_SPACE(np->dev), |
| 462 | if (dev_hard_header(send_skb, skb->dev, ptype, | 470 | LL_RESERVED_SPACE(np->dev)); |
| 463 | sha, np->dev->dev_addr, | 471 | if (!send_skb) |
| 464 | send_skb->len) < 0) { | 472 | continue; |
| 465 | kfree_skb(send_skb); | ||
| 466 | return; | ||
| 467 | } | ||
| 468 | 473 | ||
| 469 | /* | 474 | skb_reset_network_header(send_skb); |
| 470 | * Fill out the arp protocol part. | 475 | arp = (struct arphdr *) skb_put(send_skb, size); |
| 471 | * | 476 | send_skb->dev = skb->dev; |
| 472 | * we only support ethernet device type, | 477 | send_skb->protocol = htons(ETH_P_ARP); |
| 473 | * which (according to RFC 1390) should always equal 1 (Ethernet). | ||
| 474 | */ | ||
| 475 | 478 | ||
| 476 | arp->ar_hrd = htons(np->dev->type); | 479 | /* Fill the device header for the ARP frame */ |
| 477 | arp->ar_pro = htons(ETH_P_IP); | 480 | if (dev_hard_header(send_skb, skb->dev, ptype, |
| 478 | arp->ar_hln = np->dev->addr_len; | 481 | sha, np->dev->dev_addr, |
| 479 | arp->ar_pln = 4; | 482 | send_skb->len) < 0) { |
| 480 | arp->ar_op = htons(type); | 483 | kfree_skb(send_skb); |
| 484 | continue; | ||
| 485 | } | ||
| 481 | 486 | ||
| 482 | arp_ptr=(unsigned char *)(arp + 1); | 487 | /* |
| 483 | memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len); | 488 | * Fill out the arp protocol part. |
| 484 | arp_ptr += np->dev->addr_len; | 489 | * |
| 485 | memcpy(arp_ptr, &tip, 4); | 490 | * we only support ethernet device type, |
| 486 | arp_ptr += 4; | 491 | * which (according to RFC 1390) should |
| 487 | memcpy(arp_ptr, sha, np->dev->addr_len); | 492 | * always equal 1 (Ethernet). |
| 488 | arp_ptr += np->dev->addr_len; | 493 | */ |
| 489 | memcpy(arp_ptr, &sip, 4); | ||
| 490 | 494 | ||
| 491 | netpoll_send_skb(np, send_skb); | 495 | arp->ar_hrd = htons(np->dev->type); |
| 496 | arp->ar_pro = htons(ETH_P_IP); | ||
| 497 | arp->ar_hln = np->dev->addr_len; | ||
| 498 | arp->ar_pln = 4; | ||
| 499 | arp->ar_op = htons(type); | ||
| 500 | |||
| 501 | arp_ptr = (unsigned char *)(arp + 1); | ||
| 502 | memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len); | ||
| 503 | arp_ptr += np->dev->addr_len; | ||
| 504 | memcpy(arp_ptr, &tip, 4); | ||
| 505 | arp_ptr += 4; | ||
| 506 | memcpy(arp_ptr, sha, np->dev->addr_len); | ||
| 507 | arp_ptr += np->dev->addr_len; | ||
| 508 | memcpy(arp_ptr, &sip, 4); | ||
| 509 | |||
| 510 | netpoll_send_skb(np, send_skb); | ||
| 511 | |||
| 512 | /* If there are several rx_hooks for the same address, | ||
| 513 | we're fine by sending a single reply */ | ||
| 514 | break; | ||
| 515 | } | ||
| 516 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | ||
| 492 | } | 517 | } |
| 493 | 518 | ||
| 494 | int __netpoll_rx(struct sk_buff *skb) | 519 | int __netpoll_rx(struct sk_buff *skb) |
| 495 | { | 520 | { |
| 496 | int proto, len, ulen; | 521 | int proto, len, ulen; |
| 522 | int hits = 0; | ||
| 497 | struct iphdr *iph; | 523 | struct iphdr *iph; |
| 498 | struct udphdr *uh; | 524 | struct udphdr *uh; |
| 499 | struct netpoll_info *npi = skb->dev->npinfo; | 525 | struct netpoll_info *npinfo = skb->dev->npinfo; |
| 500 | struct netpoll *np = npi->rx_np; | 526 | struct netpoll *np, *tmp; |
| 501 | 527 | ||
| 502 | if (!np) | 528 | if (list_empty(&npinfo->rx_np)) |
| 503 | goto out; | 529 | goto out; |
| 530 | |||
| 504 | if (skb->dev->type != ARPHRD_ETHER) | 531 | if (skb->dev->type != ARPHRD_ETHER) |
| 505 | goto out; | 532 | goto out; |
| 506 | 533 | ||
| 507 | /* check if netpoll clients need ARP */ | 534 | /* check if netpoll clients need ARP */ |
| 508 | if (skb->protocol == htons(ETH_P_ARP) && | 535 | if (skb->protocol == htons(ETH_P_ARP) && |
| 509 | atomic_read(&trapped)) { | 536 | atomic_read(&trapped)) { |
| 510 | skb_queue_tail(&npi->arp_tx, skb); | 537 | skb_queue_tail(&npinfo->arp_tx, skb); |
| 511 | return 1; | 538 | return 1; |
| 512 | } | 539 | } |
| 513 | 540 | ||
| @@ -551,16 +578,23 @@ int __netpoll_rx(struct sk_buff *skb) | |||
| 551 | goto out; | 578 | goto out; |
| 552 | if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr)) | 579 | if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr)) |
| 553 | goto out; | 580 | goto out; |
| 554 | if (np->local_ip && np->local_ip != iph->daddr) | ||
| 555 | goto out; | ||
| 556 | if (np->remote_ip && np->remote_ip != iph->saddr) | ||
| 557 | goto out; | ||
| 558 | if (np->local_port && np->local_port != ntohs(uh->dest)) | ||
| 559 | goto out; | ||
| 560 | 581 | ||
| 561 | np->rx_hook(np, ntohs(uh->source), | 582 | list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { |
| 562 | (char *)(uh+1), | 583 | if (np->local_ip && np->local_ip != iph->daddr) |
| 563 | ulen - sizeof(struct udphdr)); | 584 | continue; |
| 585 | if (np->remote_ip && np->remote_ip != iph->saddr) | ||
| 586 | continue; | ||
| 587 | if (np->local_port && np->local_port != ntohs(uh->dest)) | ||
| 588 | continue; | ||
| 589 | |||
| 590 | np->rx_hook(np, ntohs(uh->source), | ||
| 591 | (char *)(uh+1), | ||
| 592 | ulen - sizeof(struct udphdr)); | ||
| 593 | hits++; | ||
| 594 | } | ||
| 595 | |||
| 596 | if (!hits) | ||
| 597 | goto out; | ||
| 564 | 598 | ||
| 565 | kfree_skb(skb); | 599 | kfree_skb(skb); |
| 566 | return 1; | 600 | return 1; |
| @@ -580,7 +614,7 @@ void netpoll_print_options(struct netpoll *np) | |||
| 580 | np->name, np->local_port); | 614 | np->name, np->local_port); |
| 581 | printk(KERN_INFO "%s: local IP %pI4\n", | 615 | printk(KERN_INFO "%s: local IP %pI4\n", |
| 582 | np->name, &np->local_ip); | 616 | np->name, &np->local_ip); |
| 583 | printk(KERN_INFO "%s: interface %s\n", | 617 | printk(KERN_INFO "%s: interface '%s'\n", |
| 584 | np->name, np->dev_name); | 618 | np->name, np->dev_name); |
| 585 | printk(KERN_INFO "%s: remote port %d\n", | 619 | printk(KERN_INFO "%s: remote port %d\n", |
| 586 | np->name, np->remote_port); | 620 | np->name, np->remote_port); |
| @@ -627,6 +661,9 @@ int netpoll_parse_options(struct netpoll *np, char *opt) | |||
| 627 | if ((delim = strchr(cur, '@')) == NULL) | 661 | if ((delim = strchr(cur, '@')) == NULL) |
| 628 | goto parse_failed; | 662 | goto parse_failed; |
| 629 | *delim = 0; | 663 | *delim = 0; |
| 664 | if (*cur == ' ' || *cur == '\t') | ||
| 665 | printk(KERN_INFO "%s: warning: whitespace" | ||
| 666 | "is not allowed\n", np->name); | ||
| 630 | np->remote_port = simple_strtol(cur, NULL, 10); | 667 | np->remote_port = simple_strtol(cur, NULL, 10); |
| 631 | cur = delim; | 668 | cur = delim; |
| 632 | } | 669 | } |
| @@ -674,7 +711,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) | |||
| 674 | return 0; | 711 | return 0; |
| 675 | 712 | ||
| 676 | parse_failed: | 713 | parse_failed: |
| 677 | printk(KERN_INFO "%s: couldn't parse config at %s!\n", | 714 | printk(KERN_INFO "%s: couldn't parse config at '%s'!\n", |
| 678 | np->name, cur); | 715 | np->name, cur); |
| 679 | return -1; | 716 | return -1; |
| 680 | } | 717 | } |
| @@ -684,6 +721,7 @@ int netpoll_setup(struct netpoll *np) | |||
| 684 | struct net_device *ndev = NULL; | 721 | struct net_device *ndev = NULL; |
| 685 | struct in_device *in_dev; | 722 | struct in_device *in_dev; |
| 686 | struct netpoll_info *npinfo; | 723 | struct netpoll_info *npinfo; |
| 724 | struct netpoll *npe, *tmp; | ||
| 687 | unsigned long flags; | 725 | unsigned long flags; |
| 688 | int err; | 726 | int err; |
| 689 | 727 | ||
| @@ -700,11 +738,11 @@ int netpoll_setup(struct netpoll *np) | |||
| 700 | npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); | 738 | npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); |
| 701 | if (!npinfo) { | 739 | if (!npinfo) { |
| 702 | err = -ENOMEM; | 740 | err = -ENOMEM; |
| 703 | goto release; | 741 | goto put; |
| 704 | } | 742 | } |
| 705 | 743 | ||
| 706 | npinfo->rx_flags = 0; | 744 | npinfo->rx_flags = 0; |
| 707 | npinfo->rx_np = NULL; | 745 | INIT_LIST_HEAD(&npinfo->rx_np); |
| 708 | 746 | ||
| 709 | spin_lock_init(&npinfo->rx_lock); | 747 | spin_lock_init(&npinfo->rx_lock); |
| 710 | skb_queue_head_init(&npinfo->arp_tx); | 748 | skb_queue_head_init(&npinfo->arp_tx); |
| @@ -785,7 +823,7 @@ int netpoll_setup(struct netpoll *np) | |||
| 785 | if (np->rx_hook) { | 823 | if (np->rx_hook) { |
| 786 | spin_lock_irqsave(&npinfo->rx_lock, flags); | 824 | spin_lock_irqsave(&npinfo->rx_lock, flags); |
| 787 | npinfo->rx_flags |= NETPOLL_RX_ENABLED; | 825 | npinfo->rx_flags |= NETPOLL_RX_ENABLED; |
| 788 | npinfo->rx_np = np; | 826 | list_add_tail(&np->rx, &npinfo->rx_np); |
| 789 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | 827 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); |
| 790 | } | 828 | } |
| 791 | 829 | ||
| @@ -801,9 +839,16 @@ int netpoll_setup(struct netpoll *np) | |||
| 801 | return 0; | 839 | return 0; |
| 802 | 840 | ||
| 803 | release: | 841 | release: |
| 804 | if (!ndev->npinfo) | 842 | if (!ndev->npinfo) { |
| 843 | spin_lock_irqsave(&npinfo->rx_lock, flags); | ||
| 844 | list_for_each_entry_safe(npe, tmp, &npinfo->rx_np, rx) { | ||
| 845 | npe->dev = NULL; | ||
| 846 | } | ||
| 847 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | ||
| 848 | |||
| 805 | kfree(npinfo); | 849 | kfree(npinfo); |
| 806 | np->dev = NULL; | 850 | } |
| 851 | put: | ||
| 807 | dev_put(ndev); | 852 | dev_put(ndev); |
| 808 | return err; | 853 | return err; |
| 809 | } | 854 | } |
| @@ -823,10 +868,11 @@ void netpoll_cleanup(struct netpoll *np) | |||
| 823 | if (np->dev) { | 868 | if (np->dev) { |
| 824 | npinfo = np->dev->npinfo; | 869 | npinfo = np->dev->npinfo; |
| 825 | if (npinfo) { | 870 | if (npinfo) { |
| 826 | if (npinfo->rx_np == np) { | 871 | if (!list_empty(&npinfo->rx_np)) { |
| 827 | spin_lock_irqsave(&npinfo->rx_lock, flags); | 872 | spin_lock_irqsave(&npinfo->rx_lock, flags); |
| 828 | npinfo->rx_np = NULL; | 873 | list_del(&np->rx); |
| 829 | npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; | 874 | if (list_empty(&npinfo->rx_np)) |
| 875 | npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; | ||
| 830 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | 876 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); |
| 831 | } | 877 | } |
| 832 | 878 | ||
