linux/drivers/net/xen-netback/xenbus.c
<<
>>
Prefs
   1/*
   2 * Xenbus code for netif backend
   3 *
   4 * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
   5 * Copyright (C) 2005 XenSource Ltd
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20*/
  21
  22#include "common.h"
  23
  24struct backend_info {
  25        struct xenbus_device *dev;
  26        struct xenvif *vif;
  27        enum xenbus_state frontend_state;
  28        struct xenbus_watch hotplug_status_watch;
  29        u8 have_hotplug_status_watch:1;
  30};
  31
  32static int connect_rings(struct backend_info *);
  33static void connect(struct backend_info *);
  34static void backend_create_xenvif(struct backend_info *be);
  35static void unregister_hotplug_status_watch(struct backend_info *be);
  36
  37static int netback_remove(struct xenbus_device *dev)
  38{
  39        struct backend_info *be = dev_get_drvdata(&dev->dev);
  40
  41        unregister_hotplug_status_watch(be);
  42        if (be->vif) {
  43                kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
  44                xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
  45                xenvif_disconnect(be->vif);
  46                be->vif = NULL;
  47        }
  48        kfree(be);
  49        dev_set_drvdata(&dev->dev, NULL);
  50        return 0;
  51}
  52
  53
  54/**
  55 * Entry point to this code when a new device is created.  Allocate the basic
  56 * structures and switch to InitWait.
  57 */
  58static int netback_probe(struct xenbus_device *dev,
  59                         const struct xenbus_device_id *id)
  60{
  61        const char *message;
  62        struct xenbus_transaction xbt;
  63        int err;
  64        int sg;
  65        struct backend_info *be = kzalloc(sizeof(struct backend_info),
  66                                          GFP_KERNEL);
  67        if (!be) {
  68                xenbus_dev_fatal(dev, -ENOMEM,
  69                                 "allocating backend structure");
  70                return -ENOMEM;
  71        }
  72
  73        be->dev = dev;
  74        dev_set_drvdata(&dev->dev, be);
  75
  76        sg = 1;
  77
  78        do {
  79                err = xenbus_transaction_start(&xbt);
  80                if (err) {
  81                        xenbus_dev_fatal(dev, err, "starting transaction");
  82                        goto fail;
  83                }
  84
  85                err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", sg);
  86                if (err) {
  87                        message = "writing feature-sg";
  88                        goto abort_transaction;
  89                }
  90
  91                err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4",
  92                                    "%d", sg);
  93                if (err) {
  94                        message = "writing feature-gso-tcpv4";
  95                        goto abort_transaction;
  96                }
  97
  98                /* We support rx-copy path. */
  99                err = xenbus_printf(xbt, dev->nodename,
 100                                    "feature-rx-copy", "%d", 1);
 101                if (err) {
 102                        message = "writing feature-rx-copy";
 103                        goto abort_transaction;
 104                }
 105
 106                /*
 107                 * We don't support rx-flip path (except old guests who don't
 108                 * grok this feature flag).
 109                 */
 110                err = xenbus_printf(xbt, dev->nodename,
 111                                    "feature-rx-flip", "%d", 0);
 112                if (err) {
 113                        message = "writing feature-rx-flip";
 114                        goto abort_transaction;
 115                }
 116
 117                err = xenbus_transaction_end(xbt, 0);
 118        } while (err == -EAGAIN);
 119
 120        if (err) {
 121                xenbus_dev_fatal(dev, err, "completing transaction");
 122                goto fail;
 123        }
 124
 125        err = xenbus_switch_state(dev, XenbusStateInitWait);
 126        if (err)
 127                goto fail;
 128
 129        /* This kicks hotplug scripts, so do it immediately. */
 130        backend_create_xenvif(be);
 131
 132        return 0;
 133
 134abort_transaction:
 135        xenbus_transaction_end(xbt, 1);
 136        xenbus_dev_fatal(dev, err, "%s", message);
 137fail:
 138        pr_debug("failed");
 139        netback_remove(dev);
 140        return err;
 141}
 142
 143
 144/*
 145 * Handle the creation of the hotplug script environment.  We add the script
 146 * and vif variables to the environment, for the benefit of the vif-* hotplug
 147 * scripts.
 148 */
 149static int netback_uevent(struct xenbus_device *xdev,
 150                          struct kobj_uevent_env *env)
 151{
 152        struct backend_info *be = dev_get_drvdata(&xdev->dev);
 153        char *val;
 154
 155        val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL);
 156        if (IS_ERR(val)) {
 157                int err = PTR_ERR(val);
 158                xenbus_dev_fatal(xdev, err, "reading script");
 159                return err;
 160        } else {
 161                if (add_uevent_var(env, "script=%s", val)) {
 162                        kfree(val);
 163                        return -ENOMEM;
 164                }
 165                kfree(val);
 166        }
 167
 168        if (!be || !be->vif)
 169                return 0;
 170
 171        return add_uevent_var(env, "vif=%s", be->vif->dev->name);
 172}
 173
 174
 175static void backend_create_xenvif(struct backend_info *be)
 176{
 177        int err;
 178        long handle;
 179        struct xenbus_device *dev = be->dev;
 180
 181        if (be->vif != NULL)
 182                return;
 183
 184        err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%li", &handle);
 185        if (err != 1) {
 186                xenbus_dev_fatal(dev, err, "reading handle");
 187                return;
 188        }
 189
 190        be->vif = xenvif_alloc(&dev->dev, dev->otherend_id, handle);
 191        if (IS_ERR(be->vif)) {
 192                err = PTR_ERR(be->vif);
 193                be->vif = NULL;
 194                xenbus_dev_fatal(dev, err, "creating interface");
 195                return;
 196        }
 197
 198        kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
 199}
 200
 201
 202static void disconnect_backend(struct xenbus_device *dev)
 203{
 204        struct backend_info *be = dev_get_drvdata(&dev->dev);
 205
 206        if (be->vif) {
 207                xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
 208                xenvif_disconnect(be->vif);
 209                be->vif = NULL;
 210        }
 211}
 212
 213/**
 214 * Callback received when the frontend's state changes.
 215 */
 216static void frontend_changed(struct xenbus_device *dev,
 217                             enum xenbus_state frontend_state)
 218{
 219        struct backend_info *be = dev_get_drvdata(&dev->dev);
 220
 221        pr_debug("frontend state %s", xenbus_strstate(frontend_state));
 222
 223        be->frontend_state = frontend_state;
 224
 225        switch (frontend_state) {
 226        case XenbusStateInitialising:
 227                if (dev->state == XenbusStateClosed) {
 228                        printk(KERN_INFO "%s: %s: prepare for reconnect\n",
 229                               __func__, dev->nodename);
 230                        xenbus_switch_state(dev, XenbusStateInitWait);
 231                }
 232                break;
 233
 234        case XenbusStateInitialised:
 235                break;
 236
 237        case XenbusStateConnected:
 238                if (dev->state == XenbusStateConnected)
 239                        break;
 240                backend_create_xenvif(be);
 241                if (be->vif)
 242                        connect(be);
 243                break;
 244
 245        case XenbusStateClosing:
 246                if (be->vif)
 247                        kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
 248                disconnect_backend(dev);
 249                xenbus_switch_state(dev, XenbusStateClosing);
 250                break;
 251
 252        case XenbusStateClosed:
 253                xenbus_switch_state(dev, XenbusStateClosed);
 254                if (xenbus_dev_is_online(dev))
 255                        break;
 256                /* fall through if not online */
 257        case XenbusStateUnknown:
 258                device_unregister(&dev->dev);
 259                break;
 260
 261        default:
 262                xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
 263                                 frontend_state);
 264                break;
 265        }
 266}
 267
 268
 269static void xen_net_read_rate(struct xenbus_device *dev,
 270                              unsigned long *bytes, unsigned long *usec)
 271{
 272        char *s, *e;
 273        unsigned long b, u;
 274        char *ratestr;
 275
 276        /* Default to unlimited bandwidth. */
 277        *bytes = ~0UL;
 278        *usec = 0;
 279
 280        ratestr = xenbus_read(XBT_NIL, dev->nodename, "rate", NULL);
 281        if (IS_ERR(ratestr))
 282                return;
 283
 284        s = ratestr;
 285        b = simple_strtoul(s, &e, 10);
 286        if ((s == e) || (*e != ','))
 287                goto fail;
 288
 289        s = e + 1;
 290        u = simple_strtoul(s, &e, 10);
 291        if ((s == e) || (*e != '\0'))
 292                goto fail;
 293
 294        *bytes = b;
 295        *usec = u;
 296
 297        kfree(ratestr);
 298        return;
 299
 300 fail:
 301        pr_warn("Failed to parse network rate limit. Traffic unlimited.\n");
 302        kfree(ratestr);
 303}
 304
 305static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[])
 306{
 307        char *s, *e, *macstr;
 308        int i;
 309
 310        macstr = s = xenbus_read(XBT_NIL, dev->nodename, "mac", NULL);
 311        if (IS_ERR(macstr))
 312                return PTR_ERR(macstr);
 313
 314        for (i = 0; i < ETH_ALEN; i++) {
 315                mac[i] = simple_strtoul(s, &e, 16);
 316                if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
 317                        kfree(macstr);
 318                        return -ENOENT;
 319                }
 320                s = e+1;
 321        }
 322
 323        kfree(macstr);
 324        return 0;
 325}
 326
 327static void unregister_hotplug_status_watch(struct backend_info *be)
 328{
 329        if (be->have_hotplug_status_watch) {
 330                unregister_xenbus_watch(&be->hotplug_status_watch);
 331                kfree(be->hotplug_status_watch.node);
 332        }
 333        be->have_hotplug_status_watch = 0;
 334}
 335
 336static void hotplug_status_changed(struct xenbus_watch *watch,
 337                                   const char **vec,
 338                                   unsigned int vec_size)
 339{
 340        struct backend_info *be = container_of(watch,
 341                                               struct backend_info,
 342                                               hotplug_status_watch);
 343        char *str;
 344        unsigned int len;
 345
 346        str = xenbus_read(XBT_NIL, be->dev->nodename, "hotplug-status", &len);
 347        if (IS_ERR(str))
 348                return;
 349        if (len == sizeof("connected")-1 && !memcmp(str, "connected", len)) {
 350                xenbus_switch_state(be->dev, XenbusStateConnected);
 351                /* Not interested in this watch anymore. */
 352                unregister_hotplug_status_watch(be);
 353        }
 354        kfree(str);
 355}
 356
 357static void connect(struct backend_info *be)
 358{
 359        int err;
 360        struct xenbus_device *dev = be->dev;
 361
 362        err = connect_rings(be);
 363        if (err)
 364                return;
 365
 366        err = xen_net_read_mac(dev, be->vif->fe_dev_addr);
 367        if (err) {
 368                xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
 369                return;
 370        }
 371
 372        xen_net_read_rate(dev, &be->vif->credit_bytes,
 373                          &be->vif->credit_usec);
 374        be->vif->remaining_credit = be->vif->credit_bytes;
 375
 376        unregister_hotplug_status_watch(be);
 377        err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
 378                                   hotplug_status_changed,
 379                                   "%s/%s", dev->nodename, "hotplug-status");
 380        if (err) {
 381                /* Switch now, since we can't do a watch. */
 382                xenbus_switch_state(dev, XenbusStateConnected);
 383        } else {
 384                be->have_hotplug_status_watch = 1;
 385        }
 386
 387        netif_wake_queue(be->vif->dev);
 388}
 389
 390
 391static int connect_rings(struct backend_info *be)
 392{
 393        struct xenvif *vif = be->vif;
 394        struct xenbus_device *dev = be->dev;
 395        unsigned long tx_ring_ref, rx_ring_ref;
 396        unsigned int evtchn, rx_copy;
 397        int err;
 398        int val;
 399
 400        err = xenbus_gather(XBT_NIL, dev->otherend,
 401                            "tx-ring-ref", "%lu", &tx_ring_ref,
 402                            "rx-ring-ref", "%lu", &rx_ring_ref,
 403                            "event-channel", "%u", &evtchn, NULL);
 404        if (err) {
 405                xenbus_dev_fatal(dev, err,
 406                                 "reading %s/ring-ref and event-channel",
 407                                 dev->otherend);
 408                return err;
 409        }
 410
 411        err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u",
 412                           &rx_copy);
 413        if (err == -ENOENT) {
 414                err = 0;
 415                rx_copy = 0;
 416        }
 417        if (err < 0) {
 418                xenbus_dev_fatal(dev, err, "reading %s/request-rx-copy",
 419                                 dev->otherend);
 420                return err;
 421        }
 422        if (!rx_copy)
 423                return -EOPNOTSUPP;
 424
 425        if (vif->dev->tx_queue_len != 0) {
 426                if (xenbus_scanf(XBT_NIL, dev->otherend,
 427                                 "feature-rx-notify", "%d", &val) < 0)
 428                        val = 0;
 429                if (val)
 430                        vif->can_queue = 1;
 431                else
 432                        /* Must be non-zero for pfifo_fast to work. */
 433                        vif->dev->tx_queue_len = 1;
 434        }
 435
 436        if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg",
 437                         "%d", &val) < 0)
 438                val = 0;
 439        vif->can_sg = !!val;
 440
 441        if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4",
 442                         "%d", &val) < 0)
 443                val = 0;
 444        vif->gso = !!val;
 445
 446        if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4-prefix",
 447                         "%d", &val) < 0)
 448                val = 0;
 449        vif->gso_prefix = !!val;
 450
 451        if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
 452                         "%d", &val) < 0)
 453                val = 0;
 454        vif->csum = !val;
 455
 456        /* Map the shared frame, irq etc. */
 457        err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref, evtchn);
 458        if (err) {
 459                xenbus_dev_fatal(dev, err,
 460                                 "mapping shared-frames %lu/%lu port %u",
 461                                 tx_ring_ref, rx_ring_ref, evtchn);
 462                return err;
 463        }
 464        return 0;
 465}
 466
 467
 468/* ** Driver Registration ** */
 469
 470
 471static const struct xenbus_device_id netback_ids[] = {
 472        { "vif" },
 473        { "" }
 474};
 475
 476
 477static DEFINE_XENBUS_DRIVER(netback, ,
 478        .probe = netback_probe,
 479        .remove = netback_remove,
 480        .uevent = netback_uevent,
 481        .otherend_changed = frontend_changed,
 482);
 483
 484int xenvif_xenbus_init(void)
 485{
 486        return xenbus_register_backend(&netback_driver);
 487}
 488