aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/xen-netback
diff options
context:
space:
mode:
authorPaul Durrant <Paul.Durrant@citrix.com>2016-02-02 06:55:05 -0500
committerDavid S. Miller <davem@davemloft.net>2016-02-07 13:58:36 -0500
commit22fae97d863679994b951799dd4bbe7afd95897b (patch)
treeffbee4449e8886c8557275e0b39de16455ac7a14 /drivers/net/xen-netback
parentce30905aa1a97745e73c9c847dfae19442693b64 (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.h1
-rw-r--r--drivers/net/xen-netback/xenbus.c89
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
686static int xen_register_watchers(struct xenbus_device *dev, struct xenvif *vif) 694static 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
711static void xen_unregister_watchers(struct xenvif *vif) 720static 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
729static 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
743static 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
776static 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
785static 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
792static void xen_unregister_watchers(struct xenvif *vif)
793{
794 xen_unregister_mcast_ctrl_watch(vif);
795 xen_unregister_credit_watch(vif);
796}
797
720static void unregister_hotplug_status_watch(struct backend_info *be) 798static 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