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 | ||