diff options
| author | Paul Durrant <Paul.Durrant@citrix.com> | 2016-02-02 06:55:05 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2016-02-07 13:58:36 -0500 |
| commit | 22fae97d863679994b951799dd4bbe7afd95897b (patch) | |
| tree | ffbee4449e8886c8557275e0b39de16455ac7a14 /drivers/net/xen-netback | |
| parent | ce30905aa1a97745e73c9c847dfae19442693b64 (diff) | |
xen-netback: implement dynamic multicast control
My recent patch to the Xen Project documents a protocol for 'dynamic
multicast control' in netif.h. This extends the previous multicast control
protocol to not require a shared ring reconnection to turn the feature off.
Instead the backend watches the "request-multicast-control" key in xenstore
and turns the feature off if the key value is written to zero.
This patch adds support for dynamic multicast control in xen-netback.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/xen-netback')
| -rw-r--r-- | drivers/net/xen-netback/common.h | 1 | ||||
| -rw-r--r-- | drivers/net/xen-netback/xenbus.c | 89 |
2 files changed, 82 insertions, 8 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 0333ab0fd926..112825200d41 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
| @@ -251,6 +251,7 @@ struct xenvif { | |||
| 251 | unsigned int stalled_queues; | 251 | unsigned int stalled_queues; |
| 252 | 252 | ||
| 253 | struct xenbus_watch credit_watch; | 253 | struct xenbus_watch credit_watch; |
| 254 | struct xenbus_watch mcast_ctrl_watch; | ||
| 254 | 255 | ||
| 255 | spinlock_t lock; | 256 | spinlock_t lock; |
| 256 | 257 | ||
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 56ebd8267386..39a303de20dd 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c | |||
| @@ -327,7 +327,7 @@ static int netback_probe(struct xenbus_device *dev, | |||
| 327 | goto abort_transaction; | 327 | goto abort_transaction; |
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | /* We support multicast-control. */ | 330 | /* We support dynamic multicast-control. */ |
| 331 | err = xenbus_printf(xbt, dev->nodename, | 331 | err = xenbus_printf(xbt, dev->nodename, |
| 332 | "feature-multicast-control", "%d", 1); | 332 | "feature-multicast-control", "%d", 1); |
| 333 | if (err) { | 333 | if (err) { |
| @@ -335,6 +335,14 @@ static int netback_probe(struct xenbus_device *dev, | |||
| 335 | goto abort_transaction; | 335 | goto abort_transaction; |
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | err = xenbus_printf(xbt, dev->nodename, | ||
| 339 | "feature-dynamic-multicast-control", | ||
| 340 | "%d", 1); | ||
| 341 | if (err) { | ||
| 342 | message = "writing feature-dynamic-multicast-control"; | ||
| 343 | goto abort_transaction; | ||
| 344 | } | ||
| 345 | |||
| 338 | err = xenbus_transaction_end(xbt, 0); | 346 | err = xenbus_transaction_end(xbt, 0); |
| 339 | } while (err == -EAGAIN); | 347 | } while (err == -EAGAIN); |
| 340 | 348 | ||
| @@ -683,7 +691,8 @@ static void xen_net_rate_changed(struct xenbus_watch *watch, | |||
| 683 | } | 691 | } |
| 684 | } | 692 | } |
| 685 | 693 | ||
| 686 | static int xen_register_watchers(struct xenbus_device *dev, struct xenvif *vif) | 694 | static int xen_register_credit_watch(struct xenbus_device *dev, |
| 695 | struct xenvif *vif) | ||
| 687 | { | 696 | { |
| 688 | int err = 0; | 697 | int err = 0; |
| 689 | char *node; | 698 | char *node; |
| @@ -708,7 +717,7 @@ static int xen_register_watchers(struct xenbus_device *dev, struct xenvif *vif) | |||
| 708 | return err; | 717 | return err; |
| 709 | } | 718 | } |
| 710 | 719 | ||
| 711 | static void xen_unregister_watchers(struct xenvif *vif) | 720 | static void xen_unregister_credit_watch(struct xenvif *vif) |
| 712 | { | 721 | { |
| 713 | if (vif->credit_watch.node) { | 722 | if (vif->credit_watch.node) { |
| 714 | unregister_xenbus_watch(&vif->credit_watch); | 723 | unregister_xenbus_watch(&vif->credit_watch); |
| @@ -717,6 +726,75 @@ static void xen_unregister_watchers(struct xenvif *vif) | |||
| 717 | } | 726 | } |
| 718 | } | 727 | } |
| 719 | 728 | ||
| 729 | static void xen_mcast_ctrl_changed(struct xenbus_watch *watch, | ||
| 730 | const char **vec, unsigned int len) | ||
| 731 | { | ||
| 732 | struct xenvif *vif = container_of(watch, struct xenvif, | ||
| 733 | mcast_ctrl_watch); | ||
| 734 | struct xenbus_device *dev = xenvif_to_xenbus_device(vif); | ||
| 735 | int val; | ||
| 736 | |||
| 737 | if (xenbus_scanf(XBT_NIL, dev->otherend, | ||
| 738 | "request-multicast-control", "%d", &val) < 0) | ||
| 739 | val = 0; | ||
| 740 | vif->multicast_control = !!val; | ||
| 741 | } | ||
| 742 | |||
| 743 | static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev, | ||
| 744 | struct xenvif *vif) | ||
| 745 | { | ||
| 746 | int err = 0; | ||
| 747 | char *node; | ||
| 748 | unsigned maxlen = strlen(dev->otherend) + | ||
| 749 | sizeof("/request-multicast-control"); | ||
| 750 | |||
| 751 | if (vif->mcast_ctrl_watch.node) { | ||
| 752 | pr_err_ratelimited("Watch is already registered\n"); | ||
| 753 | return -EADDRINUSE; | ||
| 754 | } | ||
| 755 | |||
| 756 | node = kmalloc(maxlen, GFP_KERNEL); | ||
| 757 | if (!node) { | ||
| 758 | pr_err("Failed to allocate memory for watch\n"); | ||
| 759 | return -ENOMEM; | ||
| 760 | } | ||
| 761 | snprintf(node, maxlen, "%s/request-multicast-control", | ||
| 762 | dev->otherend); | ||
| 763 | vif->mcast_ctrl_watch.node = node; | ||
| 764 | vif->mcast_ctrl_watch.callback = xen_mcast_ctrl_changed; | ||
| 765 | err = register_xenbus_watch(&vif->mcast_ctrl_watch); | ||
| 766 | if (err) { | ||
| 767 | pr_err("Failed to set watcher %s\n", | ||
| 768 | vif->mcast_ctrl_watch.node); | ||
| 769 | kfree(node); | ||
| 770 | vif->mcast_ctrl_watch.node = NULL; | ||
| 771 | vif->mcast_ctrl_watch.callback = NULL; | ||
| 772 | } | ||
| 773 | return err; | ||
| 774 | } | ||
| 775 | |||
| 776 | static void xen_unregister_mcast_ctrl_watch(struct xenvif *vif) | ||
| 777 | { | ||
| 778 | if (vif->mcast_ctrl_watch.node) { | ||
| 779 | unregister_xenbus_watch(&vif->mcast_ctrl_watch); | ||
| 780 | kfree(vif->mcast_ctrl_watch.node); | ||
| 781 | vif->mcast_ctrl_watch.node = NULL; | ||
| 782 | } | ||
| 783 | } | ||
| 784 | |||
| 785 | static void xen_register_watchers(struct xenbus_device *dev, | ||
| 786 | struct xenvif *vif) | ||
| 787 | { | ||
| 788 | xen_register_credit_watch(dev, vif); | ||
| 789 | xen_register_mcast_ctrl_watch(dev, vif); | ||
| 790 | } | ||
| 791 | |||
| 792 | static void xen_unregister_watchers(struct xenvif *vif) | ||
| 793 | { | ||
| 794 | xen_unregister_mcast_ctrl_watch(vif); | ||
| 795 | xen_unregister_credit_watch(vif); | ||
| 796 | } | ||
| 797 | |||
| 720 | static void unregister_hotplug_status_watch(struct backend_info *be) | 798 | static void unregister_hotplug_status_watch(struct backend_info *be) |
| 721 | { | 799 | { |
| 722 | if (be->have_hotplug_status_watch) { | 800 | if (be->have_hotplug_status_watch) { |
| @@ -1030,11 +1108,6 @@ static int read_xenbus_vif_flags(struct backend_info *be) | |||
| 1030 | val = 0; | 1108 | val = 0; |
| 1031 | vif->ipv6_csum = !!val; | 1109 | vif->ipv6_csum = !!val; |
| 1032 | 1110 | ||
| 1033 | if (xenbus_scanf(XBT_NIL, dev->otherend, "request-multicast-control", | ||
| 1034 | "%d", &val) < 0) | ||
| 1035 | val = 0; | ||
| 1036 | vif->multicast_control = !!val; | ||
| 1037 | |||
| 1038 | return 0; | 1111 | return 0; |
| 1039 | } | 1112 | } |
| 1040 | 1113 | ||
