2
0

xen_nic.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. /*
  2. * xen paravirt network card backend
  3. *
  4. * (c) Gerd Hoffmann <kraxel@redhat.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; under version 2 of the License.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * Contributions after 2012-01-13 are licensed under the terms of the
  19. * GNU GPL, version 2 or (at your option) any later version.
  20. */
  21. #include "qemu/osdep.h"
  22. #include "qemu/main-loop.h"
  23. #include "qemu/cutils.h"
  24. #include "qemu/log.h"
  25. #include "qemu/qemu-print.h"
  26. #include "qobject/qdict.h"
  27. #include "qapi/error.h"
  28. #include <sys/socket.h>
  29. #include <sys/ioctl.h>
  30. #include <sys/wait.h>
  31. #include "net/net.h"
  32. #include "net/checksum.h"
  33. #include "net/util.h"
  34. #include "hw/xen/xen-backend.h"
  35. #include "hw/xen/xen-bus-helper.h"
  36. #include "hw/qdev-properties.h"
  37. #include "hw/qdev-properties-system.h"
  38. #include "hw/xen/interface/io/netif.h"
  39. #include "hw/xen/interface/io/xs_wire.h"
  40. #include "trace.h"
  41. /* ------------------------------------------------------------- */
  42. struct XenNetDev {
  43. struct XenDevice xendev; /* must be first */
  44. XenEventChannel *event_channel;
  45. int dev;
  46. int tx_work;
  47. unsigned int tx_ring_ref;
  48. unsigned int rx_ring_ref;
  49. struct netif_tx_sring *txs;
  50. struct netif_rx_sring *rxs;
  51. netif_tx_back_ring_t tx_ring;
  52. netif_rx_back_ring_t rx_ring;
  53. NICConf conf;
  54. NICState *nic;
  55. };
  56. typedef struct XenNetDev XenNetDev;
  57. #define TYPE_XEN_NET_DEVICE "xen-net-device"
  58. OBJECT_DECLARE_SIMPLE_TYPE(XenNetDev, XEN_NET_DEVICE)
  59. /* ------------------------------------------------------------- */
  60. static void net_tx_response(struct XenNetDev *netdev, netif_tx_request_t *txp, int8_t st)
  61. {
  62. RING_IDX i = netdev->tx_ring.rsp_prod_pvt;
  63. netif_tx_response_t *resp;
  64. int notify;
  65. resp = RING_GET_RESPONSE(&netdev->tx_ring, i);
  66. resp->id = txp->id;
  67. resp->status = st;
  68. #if 0
  69. if (txp->flags & NETTXF_extra_info) {
  70. RING_GET_RESPONSE(&netdev->tx_ring, ++i)->status = NETIF_RSP_NULL;
  71. }
  72. #endif
  73. netdev->tx_ring.rsp_prod_pvt = ++i;
  74. RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netdev->tx_ring, notify);
  75. if (notify) {
  76. xen_device_notify_event_channel(XEN_DEVICE(netdev),
  77. netdev->event_channel, NULL);
  78. }
  79. if (i == netdev->tx_ring.req_cons) {
  80. int more_to_do;
  81. RING_FINAL_CHECK_FOR_REQUESTS(&netdev->tx_ring, more_to_do);
  82. if (more_to_do) {
  83. netdev->tx_work++;
  84. }
  85. }
  86. }
  87. static void net_tx_error(struct XenNetDev *netdev, netif_tx_request_t *txp, RING_IDX end)
  88. {
  89. #if 0
  90. /*
  91. * Hmm, why netback fails everything in the ring?
  92. * Should we do that even when not supporting SG and TSO?
  93. */
  94. RING_IDX cons = netdev->tx_ring.req_cons;
  95. do {
  96. make_tx_response(netif, txp, NETIF_RSP_ERROR);
  97. if (cons >= end) {
  98. break;
  99. }
  100. txp = RING_GET_REQUEST(&netdev->tx_ring, cons++);
  101. } while (1);
  102. netdev->tx_ring.req_cons = cons;
  103. netif_schedule_work(netif);
  104. netif_put(netif);
  105. #else
  106. net_tx_response(netdev, txp, NETIF_RSP_ERROR);
  107. #endif
  108. }
  109. static bool net_tx_packets(struct XenNetDev *netdev)
  110. {
  111. bool done_something = false;
  112. netif_tx_request_t txreq;
  113. RING_IDX rc, rp;
  114. void *page;
  115. void *tmpbuf = NULL;
  116. assert(bql_locked());
  117. for (;;) {
  118. rc = netdev->tx_ring.req_cons;
  119. rp = netdev->tx_ring.sring->req_prod;
  120. xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
  121. while ((rc != rp)) {
  122. if (RING_REQUEST_CONS_OVERFLOW(&netdev->tx_ring, rc)) {
  123. break;
  124. }
  125. memcpy(&txreq, RING_GET_REQUEST(&netdev->tx_ring, rc), sizeof(txreq));
  126. netdev->tx_ring.req_cons = ++rc;
  127. done_something = true;
  128. #if 1
  129. /* should not happen in theory, we don't announce the *
  130. * feature-{sg,gso,whatelse} flags in xenstore (yet?) */
  131. if (txreq.flags & NETTXF_extra_info) {
  132. qemu_log_mask(LOG_UNIMP, "vif%u: FIXME: extra info flag\n",
  133. netdev->dev);
  134. net_tx_error(netdev, &txreq, rc);
  135. continue;
  136. }
  137. if (txreq.flags & NETTXF_more_data) {
  138. qemu_log_mask(LOG_UNIMP, "vif%u: FIXME: more data flag\n",
  139. netdev->dev);
  140. net_tx_error(netdev, &txreq, rc);
  141. continue;
  142. }
  143. #endif
  144. if (txreq.size < 14) {
  145. qemu_log_mask(LOG_GUEST_ERROR, "vif%u: bad packet size: %d\n",
  146. netdev->dev, txreq.size);
  147. net_tx_error(netdev, &txreq, rc);
  148. continue;
  149. }
  150. if ((txreq.offset + txreq.size) > XEN_PAGE_SIZE) {
  151. qemu_log_mask(LOG_GUEST_ERROR, "vif%u: error: page crossing\n",
  152. netdev->dev);
  153. net_tx_error(netdev, &txreq, rc);
  154. continue;
  155. }
  156. trace_xen_netdev_tx(netdev->dev, txreq.gref, txreq.offset,
  157. txreq.size, txreq.flags,
  158. (txreq.flags & NETTXF_csum_blank) ? " csum_blank" : "",
  159. (txreq.flags & NETTXF_data_validated) ? " data_validated" : "",
  160. (txreq.flags & NETTXF_more_data) ? " more_data" : "",
  161. (txreq.flags & NETTXF_extra_info) ? " extra_info" : "");
  162. page = xen_device_map_grant_refs(&netdev->xendev, &txreq.gref, 1,
  163. PROT_READ, NULL);
  164. if (page == NULL) {
  165. qemu_log_mask(LOG_GUEST_ERROR,
  166. "vif%u: tx gref dereference failed (%d)\n",
  167. netdev->dev, txreq.gref);
  168. net_tx_error(netdev, &txreq, rc);
  169. continue;
  170. }
  171. if (txreq.flags & NETTXF_csum_blank) {
  172. /* have read-only mapping -> can't fill checksum in-place */
  173. if (!tmpbuf) {
  174. tmpbuf = g_malloc(XEN_PAGE_SIZE);
  175. }
  176. memcpy(tmpbuf, page + txreq.offset, txreq.size);
  177. net_checksum_calculate(tmpbuf, txreq.size, CSUM_ALL);
  178. qemu_send_packet(qemu_get_queue(netdev->nic), tmpbuf,
  179. txreq.size);
  180. } else {
  181. qemu_send_packet(qemu_get_queue(netdev->nic),
  182. page + txreq.offset, txreq.size);
  183. }
  184. xen_device_unmap_grant_refs(&netdev->xendev, page, &txreq.gref, 1,
  185. NULL);
  186. net_tx_response(netdev, &txreq, NETIF_RSP_OKAY);
  187. }
  188. if (!netdev->tx_work) {
  189. break;
  190. }
  191. netdev->tx_work = 0;
  192. }
  193. g_free(tmpbuf);
  194. return done_something;
  195. }
  196. /* ------------------------------------------------------------- */
  197. static void net_rx_response(struct XenNetDev *netdev,
  198. netif_rx_request_t *req, int8_t st,
  199. uint16_t offset, uint16_t size,
  200. uint16_t flags)
  201. {
  202. RING_IDX i = netdev->rx_ring.rsp_prod_pvt;
  203. netif_rx_response_t *resp;
  204. int notify;
  205. resp = RING_GET_RESPONSE(&netdev->rx_ring, i);
  206. resp->offset = offset;
  207. resp->flags = flags;
  208. resp->id = req->id;
  209. resp->status = (int16_t)size;
  210. if (st < 0) {
  211. resp->status = (int16_t)st;
  212. }
  213. trace_xen_netdev_rx(netdev->dev, i, resp->status, resp->flags);
  214. netdev->rx_ring.rsp_prod_pvt = ++i;
  215. RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netdev->rx_ring, notify);
  216. if (notify) {
  217. xen_device_notify_event_channel(XEN_DEVICE(netdev),
  218. netdev->event_channel, NULL);
  219. }
  220. }
  221. #define NET_IP_ALIGN 2
  222. static ssize_t net_rx_packet(NetClientState *nc, const uint8_t *buf, size_t size)
  223. {
  224. struct XenNetDev *netdev = qemu_get_nic_opaque(nc);
  225. netif_rx_request_t rxreq;
  226. RING_IDX rc, rp;
  227. void *page;
  228. assert(bql_locked());
  229. if (xen_device_backend_get_state(&netdev->xendev) != XenbusStateConnected) {
  230. return -1;
  231. }
  232. rc = netdev->rx_ring.req_cons;
  233. rp = netdev->rx_ring.sring->req_prod;
  234. xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
  235. if (rc == rp || RING_REQUEST_CONS_OVERFLOW(&netdev->rx_ring, rc)) {
  236. return 0;
  237. }
  238. if (size > XEN_PAGE_SIZE - NET_IP_ALIGN) {
  239. qemu_log_mask(LOG_GUEST_ERROR, "vif%u: packet too big (%lu > %ld)",
  240. netdev->dev, (unsigned long)size,
  241. XEN_PAGE_SIZE - NET_IP_ALIGN);
  242. return -1;
  243. }
  244. memcpy(&rxreq, RING_GET_REQUEST(&netdev->rx_ring, rc), sizeof(rxreq));
  245. netdev->rx_ring.req_cons = ++rc;
  246. page = xen_device_map_grant_refs(&netdev->xendev, &rxreq.gref, 1,
  247. PROT_WRITE, NULL);
  248. if (page == NULL) {
  249. qemu_log_mask(LOG_GUEST_ERROR,
  250. "vif%u: rx gref dereference failed (%d)\n",
  251. netdev->dev, rxreq.gref);
  252. net_rx_response(netdev, &rxreq, NETIF_RSP_ERROR, 0, 0, 0);
  253. return -1;
  254. }
  255. memcpy(page + NET_IP_ALIGN, buf, size);
  256. xen_device_unmap_grant_refs(&netdev->xendev, page, &rxreq.gref, 1, NULL);
  257. net_rx_response(netdev, &rxreq, NETIF_RSP_OKAY, NET_IP_ALIGN, size, 0);
  258. return size;
  259. }
  260. /* ------------------------------------------------------------- */
  261. static NetClientInfo net_xen_info = {
  262. .type = NET_CLIENT_DRIVER_NIC,
  263. .size = sizeof(NICState),
  264. .receive = net_rx_packet,
  265. };
  266. static void xen_netdev_realize(XenDevice *xendev, Error **errp)
  267. {
  268. ERRP_GUARD();
  269. XenNetDev *netdev = XEN_NET_DEVICE(xendev);
  270. NetClientState *nc;
  271. qemu_macaddr_default_if_unset(&netdev->conf.macaddr);
  272. xen_device_frontend_printf(xendev, "mac", "%02x:%02x:%02x:%02x:%02x:%02x",
  273. netdev->conf.macaddr.a[0],
  274. netdev->conf.macaddr.a[1],
  275. netdev->conf.macaddr.a[2],
  276. netdev->conf.macaddr.a[3],
  277. netdev->conf.macaddr.a[4],
  278. netdev->conf.macaddr.a[5]);
  279. netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf,
  280. object_get_typename(OBJECT(xendev)),
  281. DEVICE(xendev)->id,
  282. &xendev->qdev.mem_reentrancy_guard, netdev);
  283. nc = qemu_get_queue(netdev->nic);
  284. qemu_format_nic_info_str(nc, netdev->conf.macaddr.a);
  285. /* fill info */
  286. xen_device_backend_printf(xendev, "feature-rx-copy", "%u", 1);
  287. xen_device_backend_printf(xendev, "feature-rx-flip", "%u", 0);
  288. trace_xen_netdev_realize(netdev->dev, nc->info_str, nc->peer ?
  289. nc->peer->name : "(none)");
  290. }
  291. static bool net_event(void *_xendev)
  292. {
  293. XenNetDev *netdev = XEN_NET_DEVICE(_xendev);
  294. bool done_something;
  295. done_something = net_tx_packets(netdev);
  296. qemu_flush_queued_packets(qemu_get_queue(netdev->nic));
  297. return done_something;
  298. }
  299. static bool xen_netdev_connect(XenDevice *xendev, Error **errp)
  300. {
  301. ERRP_GUARD();
  302. XenNetDev *netdev = XEN_NET_DEVICE(xendev);
  303. unsigned int port, rx_copy;
  304. assert(bql_locked());
  305. if (xen_device_frontend_scanf(xendev, "tx-ring-ref", "%u",
  306. &netdev->tx_ring_ref) != 1) {
  307. error_setg(errp, "failed to read tx-ring-ref");
  308. return false;
  309. }
  310. if (xen_device_frontend_scanf(xendev, "rx-ring-ref", "%u",
  311. &netdev->rx_ring_ref) != 1) {
  312. error_setg(errp, "failed to read rx-ring-ref");
  313. return false;
  314. }
  315. if (xen_device_frontend_scanf(xendev, "event-channel", "%u",
  316. &port) != 1) {
  317. error_setg(errp, "failed to read event-channel");
  318. return false;
  319. }
  320. if (xen_device_frontend_scanf(xendev, "request-rx-copy", "%u",
  321. &rx_copy) != 1) {
  322. rx_copy = 0;
  323. }
  324. if (rx_copy == 0) {
  325. error_setg(errp, "frontend doesn't support rx-copy");
  326. return false;
  327. }
  328. netdev->txs = xen_device_map_grant_refs(xendev,
  329. &netdev->tx_ring_ref, 1,
  330. PROT_READ | PROT_WRITE,
  331. errp);
  332. if (!netdev->txs) {
  333. error_prepend(errp, "failed to map tx grant ref: ");
  334. return false;
  335. }
  336. netdev->rxs = xen_device_map_grant_refs(xendev,
  337. &netdev->rx_ring_ref, 1,
  338. PROT_READ | PROT_WRITE,
  339. errp);
  340. if (!netdev->rxs) {
  341. error_prepend(errp, "failed to map rx grant ref: ");
  342. return false;
  343. }
  344. BACK_RING_INIT(&netdev->tx_ring, netdev->txs, XEN_PAGE_SIZE);
  345. BACK_RING_INIT(&netdev->rx_ring, netdev->rxs, XEN_PAGE_SIZE);
  346. netdev->event_channel = xen_device_bind_event_channel(xendev, port,
  347. net_event,
  348. netdev,
  349. errp);
  350. if (!netdev->event_channel) {
  351. return false;
  352. }
  353. trace_xen_netdev_connect(netdev->dev, netdev->tx_ring_ref,
  354. netdev->rx_ring_ref, port);
  355. net_tx_packets(netdev);
  356. return true;
  357. }
  358. static void xen_netdev_disconnect(XenDevice *xendev, Error **errp)
  359. {
  360. XenNetDev *netdev = XEN_NET_DEVICE(xendev);
  361. trace_xen_netdev_disconnect(netdev->dev);
  362. assert(bql_locked());
  363. netdev->tx_ring.sring = NULL;
  364. netdev->rx_ring.sring = NULL;
  365. if (netdev->event_channel) {
  366. xen_device_unbind_event_channel(xendev, netdev->event_channel,
  367. errp);
  368. netdev->event_channel = NULL;
  369. }
  370. if (netdev->txs) {
  371. xen_device_unmap_grant_refs(xendev, netdev->txs,
  372. &netdev->tx_ring_ref, 1, errp);
  373. netdev->txs = NULL;
  374. }
  375. if (netdev->rxs) {
  376. xen_device_unmap_grant_refs(xendev, netdev->rxs,
  377. &netdev->rx_ring_ref, 1, errp);
  378. netdev->rxs = NULL;
  379. }
  380. }
  381. /* -------------------------------------------------------------------- */
  382. static void xen_netdev_frontend_changed(XenDevice *xendev,
  383. enum xenbus_state frontend_state,
  384. Error **errp)
  385. {
  386. ERRP_GUARD();
  387. enum xenbus_state backend_state = xen_device_backend_get_state(xendev);
  388. trace_xen_netdev_frontend_changed(xendev->name, frontend_state);
  389. switch (frontend_state) {
  390. case XenbusStateConnected:
  391. if (backend_state == XenbusStateConnected) {
  392. break;
  393. }
  394. xen_netdev_disconnect(xendev, errp);
  395. if (*errp) {
  396. break;
  397. }
  398. if (!xen_netdev_connect(xendev, errp)) {
  399. xen_netdev_disconnect(xendev, NULL);
  400. xen_device_backend_set_state(xendev, XenbusStateClosing);
  401. break;
  402. }
  403. xen_device_backend_set_state(xendev, XenbusStateConnected);
  404. break;
  405. case XenbusStateClosing:
  406. xen_device_backend_set_state(xendev, XenbusStateClosing);
  407. break;
  408. case XenbusStateClosed:
  409. case XenbusStateUnknown:
  410. xen_netdev_disconnect(xendev, errp);
  411. if (*errp) {
  412. break;
  413. }
  414. xen_device_backend_set_state(xendev, XenbusStateClosed);
  415. break;
  416. case XenbusStateInitialised:
  417. /*
  418. * Linux netback does nothing on the frontend going (back) to
  419. * XenbusStateInitialised, so do the same here.
  420. */
  421. default:
  422. break;
  423. }
  424. }
  425. static char *xen_netdev_get_name(XenDevice *xendev, Error **errp)
  426. {
  427. XenNetDev *netdev = XEN_NET_DEVICE(xendev);
  428. if (netdev->dev == -1) {
  429. XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
  430. int idx = (xen_mode == XEN_EMULATE) ? 0 : 1;
  431. Error *local_err = NULL;
  432. char *value;
  433. /* Theoretically we could go up to INT_MAX here but that's overkill */
  434. while (idx < 100) {
  435. value = xs_node_read(xenbus->xsh, XBT_NULL, NULL, &local_err,
  436. "/local/domain/%u/device/vif/%u",
  437. xendev->frontend_id, idx);
  438. if (!value) {
  439. if (errno == ENOENT) {
  440. netdev->dev = idx;
  441. error_free(local_err);
  442. goto found;
  443. }
  444. error_propagate(errp, local_err);
  445. return NULL;
  446. }
  447. free(value);
  448. idx++;
  449. }
  450. error_setg(errp, "cannot find device index for netdev device");
  451. return NULL;
  452. }
  453. found:
  454. return g_strdup_printf("%u", netdev->dev);
  455. }
  456. static void xen_netdev_unrealize(XenDevice *xendev)
  457. {
  458. XenNetDev *netdev = XEN_NET_DEVICE(xendev);
  459. trace_xen_netdev_unrealize(netdev->dev);
  460. /* Disconnect from the frontend in case this has not already happened */
  461. xen_netdev_disconnect(xendev, NULL);
  462. if (netdev->nic) {
  463. qemu_del_nic(netdev->nic);
  464. }
  465. }
  466. /* ------------------------------------------------------------- */
  467. static const Property xen_netdev_properties[] = {
  468. DEFINE_NIC_PROPERTIES(XenNetDev, conf),
  469. DEFINE_PROP_INT32("idx", XenNetDev, dev, -1),
  470. };
  471. static void xen_netdev_class_init(ObjectClass *class, void *data)
  472. {
  473. DeviceClass *dev_class = DEVICE_CLASS(class);
  474. XenDeviceClass *xendev_class = XEN_DEVICE_CLASS(class);
  475. xendev_class->backend = "qnic";
  476. xendev_class->device = "vif";
  477. xendev_class->get_name = xen_netdev_get_name;
  478. xendev_class->realize = xen_netdev_realize;
  479. xendev_class->frontend_changed = xen_netdev_frontend_changed;
  480. xendev_class->unrealize = xen_netdev_unrealize;
  481. set_bit(DEVICE_CATEGORY_NETWORK, dev_class->categories);
  482. dev_class->user_creatable = true;
  483. device_class_set_props(dev_class, xen_netdev_properties);
  484. }
  485. static const TypeInfo xen_net_type_info = {
  486. .name = TYPE_XEN_NET_DEVICE,
  487. .parent = TYPE_XEN_DEVICE,
  488. .instance_size = sizeof(XenNetDev),
  489. .class_init = xen_netdev_class_init,
  490. };
  491. static void xen_net_register_types(void)
  492. {
  493. type_register_static(&xen_net_type_info);
  494. }
  495. type_init(xen_net_register_types)
  496. /* Called to instantiate a XenNetDev when the backend is detected. */
  497. static void xen_net_device_create(XenBackendInstance *backend,
  498. QDict *opts, Error **errp)
  499. {
  500. ERRP_GUARD();
  501. XenBus *xenbus = xen_backend_get_bus(backend);
  502. const char *name = xen_backend_get_name(backend);
  503. XenDevice *xendev = NULL;
  504. unsigned long number;
  505. const char *macstr;
  506. XenNetDev *net;
  507. MACAddr mac;
  508. if (qemu_strtoul(name, NULL, 10, &number) || number >= INT_MAX) {
  509. error_setg(errp, "failed to parse name '%s'", name);
  510. goto fail;
  511. }
  512. trace_xen_netdev_create(number);
  513. macstr = qdict_get_try_str(opts, "mac");
  514. if (macstr == NULL) {
  515. error_setg(errp, "no MAC address found");
  516. goto fail;
  517. }
  518. if (net_parse_macaddr(mac.a, macstr) < 0) {
  519. error_setg(errp, "failed to parse MAC address");
  520. goto fail;
  521. }
  522. xendev = XEN_DEVICE(qdev_new(TYPE_XEN_NET_DEVICE));
  523. net = XEN_NET_DEVICE(xendev);
  524. net->dev = number;
  525. memcpy(&net->conf.macaddr, &mac, sizeof(mac));
  526. if (qdev_realize_and_unref(DEVICE(xendev), BUS(xenbus), errp)) {
  527. xen_backend_set_device(backend, xendev);
  528. return;
  529. }
  530. error_prepend(errp, "realization of net device %lu failed: ",
  531. number);
  532. fail:
  533. if (xendev) {
  534. object_unparent(OBJECT(xendev));
  535. }
  536. }
  537. static void xen_net_device_destroy(XenBackendInstance *backend,
  538. Error **errp)
  539. {
  540. ERRP_GUARD();
  541. XenDevice *xendev = xen_backend_get_device(backend);
  542. XenNetDev *netdev = XEN_NET_DEVICE(xendev);
  543. trace_xen_netdev_destroy(netdev->dev);
  544. object_unparent(OBJECT(xendev));
  545. }
  546. static const XenBackendInfo xen_net_backend_info = {
  547. .type = "qnic",
  548. .create = xen_net_device_create,
  549. .destroy = xen_net_device_destroy,
  550. };
  551. static void xen_net_register_backend(void)
  552. {
  553. xen_backend_register(&xen_net_backend_info);
  554. }
  555. xen_backend_init(xen_net_register_backend);