1 /*
2 * Copyright (C) 2016 SUSE Linux GmbH
3 * Author Juergen Gross <jgross@suse.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published
7 * by the Free Software Foundation; version 2.1 only. with the special
8 * exception on linking described in file 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 Lesser General Public License for more details.
14 */
15
16 #include "libxl_osdeps.h"
17
18 #include "libxl_internal.h"
19
libxl_mac_to_device_nic(libxl_ctx * ctx,uint32_t domid,const char * mac,libxl_device_nic * nic)20 int libxl_mac_to_device_nic(libxl_ctx *ctx, uint32_t domid,
21 const char *mac, libxl_device_nic *nic)
22 {
23 GC_INIT(ctx);
24 libxl_device_nic *nics;
25 int nb, rc, i;
26 libxl_mac mac_n;
27
28 rc = libxl__parse_mac(mac, mac_n);
29 if (rc)
30 return rc;
31
32 nics = libxl__device_list(gc, &libxl__nic_devtype, domid, &nb);
33 if (!nics)
34 return ERROR_FAIL;
35
36 memset(nic, 0, sizeof (libxl_device_nic));
37
38 rc = ERROR_INVAL;
39 for (i = 0; i < nb; ++i) {
40 if (!libxl__compare_macs(&mac_n, &nics[i].mac)) {
41 *nic = nics[i];
42 rc = 0;
43 i++; /* Do not dispose this NIC on exit path */
44 break;
45 }
46 libxl_device_nic_dispose(&nics[i]);
47 }
48
49 for (; i<nb; i++)
50 libxl_device_nic_dispose(&nics[i]);
51
52 free(nics);
53 return rc;
54 }
55
libxl__device_nic_setdefault(libxl__gc * gc,uint32_t domid,libxl_device_nic * nic,bool hotplug)56 static int libxl__device_nic_setdefault(libxl__gc *gc, uint32_t domid,
57 libxl_device_nic *nic, bool hotplug)
58 {
59 int rc;
60
61 if (!nic->mtu)
62 nic->mtu = 1492;
63 if (!nic->model) {
64 nic->model = strdup("rtl8139");
65 if (!nic->model) return ERROR_NOMEM;
66 }
67 if (libxl__mac_is_default(&nic->mac)) {
68 const uint8_t *r;
69 libxl_uuid uuid;
70
71 libxl_uuid_generate(&uuid);
72 r = libxl_uuid_bytearray(&uuid);
73
74 nic->mac[0] = 0x00;
75 nic->mac[1] = 0x16;
76 nic->mac[2] = 0x3e;
77 nic->mac[3] = r[0] & 0x7f;
78 nic->mac[4] = r[1];
79 nic->mac[5] = r[2];
80 }
81 if (!nic->bridge) {
82 nic->bridge = strdup("xenbr0");
83 if (!nic->bridge) return ERROR_NOMEM;
84 }
85 if ( !nic->script && asprintf(&nic->script, "%s/vif-bridge",
86 libxl__xen_script_dir_path()) < 0 )
87 return ERROR_FAIL;
88
89 rc = libxl__resolve_domid(gc, nic->backend_domname, &nic->backend_domid);
90 if (rc < 0) return rc;
91
92 switch (libxl__domain_type(gc, domid)) {
93 case LIBXL_DOMAIN_TYPE_HVM:
94 if (!nic->nictype) {
95 if (hotplug)
96 nic->nictype = LIBXL_NIC_TYPE_VIF;
97 else
98 nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
99 }
100 break;
101 case LIBXL_DOMAIN_TYPE_PVH:
102 case LIBXL_DOMAIN_TYPE_PV:
103 if (nic->nictype == LIBXL_NIC_TYPE_VIF_IOEMU) {
104 LOGD(ERROR, domid,
105 "trying to create PV or PVH guest with an emulated interface");
106 return ERROR_INVAL;
107 }
108 nic->nictype = LIBXL_NIC_TYPE_VIF;
109 break;
110 case LIBXL_DOMAIN_TYPE_INVALID:
111 return ERROR_FAIL;
112 default:
113 abort();
114 }
115
116 return rc;
117 }
118
libxl__device_from_nic(libxl__gc * gc,uint32_t domid,libxl_device_nic * nic,libxl__device * device)119 static int libxl__device_from_nic(libxl__gc *gc, uint32_t domid,
120 libxl_device_nic *nic,
121 libxl__device *device)
122 {
123 device->backend_devid = nic->devid;
124 device->backend_domid = nic->backend_domid;
125 device->backend_kind = LIBXL__DEVICE_KIND_VIF;
126 device->devid = nic->devid;
127 device->domid = domid;
128 device->kind = LIBXL__DEVICE_KIND_VIF;
129
130 return 0;
131 }
132
libxl__update_config_nic(libxl__gc * gc,libxl_device_nic * dst,const libxl_device_nic * src)133 static void libxl__update_config_nic(libxl__gc *gc, libxl_device_nic *dst,
134 const libxl_device_nic *src)
135 {
136 dst->devid = src->devid;
137 dst->nictype = src->nictype;
138 libxl_mac_copy(CTX, &dst->mac, &src->mac);
139 }
140
141 static LIBXL_DEFINE_UPDATE_DEVID(nic, "vif")
142
libxl__set_xenstore_nic(libxl__gc * gc,uint32_t domid,libxl_device_nic * nic,flexarray_t * back,flexarray_t * front,flexarray_t * ro_front)143 static int libxl__set_xenstore_nic(libxl__gc *gc, uint32_t domid,
144 libxl_device_nic *nic,
145 flexarray_t *back, flexarray_t *front,
146 flexarray_t *ro_front)
147 {
148 flexarray_grow(back, 2);
149
150 if (nic->script)
151 flexarray_append_pair(back, "script",
152 libxl__abs_path(gc, nic->script,
153 libxl__xen_script_dir_path()));
154
155 if (nic->ifname) {
156 flexarray_append(back, "vifname");
157 flexarray_append(back, nic->ifname);
158 }
159
160 if (nic->coloft_forwarddev) {
161 flexarray_append(back, "forwarddev");
162 flexarray_append(back, nic->coloft_forwarddev);
163 }
164
165 #define MAYBE_ADD_COLO_ARGS(arg) ({ \
166 if (nic->colo_##arg) { \
167 flexarray_append(back, "colo_"#arg); \
168 flexarray_append(back, nic->colo_##arg); \
169 } \
170 })
171
172 MAYBE_ADD_COLO_ARGS(sock_mirror_id);
173 MAYBE_ADD_COLO_ARGS(sock_mirror_ip);
174 MAYBE_ADD_COLO_ARGS(sock_mirror_port);
175 MAYBE_ADD_COLO_ARGS(sock_compare_pri_in_id);
176 MAYBE_ADD_COLO_ARGS(sock_compare_pri_in_ip);
177 MAYBE_ADD_COLO_ARGS(sock_compare_pri_in_port);
178 MAYBE_ADD_COLO_ARGS(sock_compare_sec_in_id);
179 MAYBE_ADD_COLO_ARGS(sock_compare_sec_in_ip);
180 MAYBE_ADD_COLO_ARGS(sock_compare_sec_in_port);
181 MAYBE_ADD_COLO_ARGS(sock_compare_notify_id);
182 MAYBE_ADD_COLO_ARGS(sock_compare_notify_ip);
183 MAYBE_ADD_COLO_ARGS(sock_compare_notify_port);
184 MAYBE_ADD_COLO_ARGS(sock_redirector0_id);
185 MAYBE_ADD_COLO_ARGS(sock_redirector0_ip);
186 MAYBE_ADD_COLO_ARGS(sock_redirector0_port);
187 MAYBE_ADD_COLO_ARGS(sock_redirector1_id);
188 MAYBE_ADD_COLO_ARGS(sock_redirector1_ip);
189 MAYBE_ADD_COLO_ARGS(sock_redirector1_port);
190 MAYBE_ADD_COLO_ARGS(sock_redirector2_id);
191 MAYBE_ADD_COLO_ARGS(sock_redirector2_ip);
192 MAYBE_ADD_COLO_ARGS(sock_redirector2_port);
193 MAYBE_ADD_COLO_ARGS(filter_mirror_queue);
194 MAYBE_ADD_COLO_ARGS(filter_mirror_outdev);
195 MAYBE_ADD_COLO_ARGS(filter_redirector0_queue);
196 MAYBE_ADD_COLO_ARGS(filter_redirector0_indev);
197 MAYBE_ADD_COLO_ARGS(filter_redirector0_outdev);
198 MAYBE_ADD_COLO_ARGS(filter_redirector1_queue);
199 MAYBE_ADD_COLO_ARGS(filter_redirector1_indev);
200 MAYBE_ADD_COLO_ARGS(filter_redirector1_outdev);
201 MAYBE_ADD_COLO_ARGS(compare_pri_in);
202 MAYBE_ADD_COLO_ARGS(compare_sec_in);
203 MAYBE_ADD_COLO_ARGS(compare_out);
204 MAYBE_ADD_COLO_ARGS(compare_notify_dev);
205
206 MAYBE_ADD_COLO_ARGS(sock_sec_redirector0_id);
207 MAYBE_ADD_COLO_ARGS(sock_sec_redirector0_ip);
208 MAYBE_ADD_COLO_ARGS(sock_sec_redirector0_port);
209 MAYBE_ADD_COLO_ARGS(sock_sec_redirector1_id);
210 MAYBE_ADD_COLO_ARGS(sock_sec_redirector1_ip);
211 MAYBE_ADD_COLO_ARGS(sock_sec_redirector1_port);
212 MAYBE_ADD_COLO_ARGS(filter_sec_redirector0_queue);
213 MAYBE_ADD_COLO_ARGS(filter_sec_redirector0_indev);
214 MAYBE_ADD_COLO_ARGS(filter_sec_redirector0_outdev);
215 MAYBE_ADD_COLO_ARGS(filter_sec_redirector1_queue);
216 MAYBE_ADD_COLO_ARGS(filter_sec_redirector1_indev);
217 MAYBE_ADD_COLO_ARGS(filter_sec_redirector1_outdev);
218 MAYBE_ADD_COLO_ARGS(filter_sec_rewriter0_queue);
219 MAYBE_ADD_COLO_ARGS(checkpoint_host);
220 MAYBE_ADD_COLO_ARGS(checkpoint_port);
221
222 #undef MAYBE_ADD_COLO_ARGS
223
224 flexarray_append(back, "mac");
225 flexarray_append(back,GCSPRINTF(LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac)));
226 if (nic->ip) {
227 flexarray_append(back, "ip");
228 flexarray_append(back, libxl__strdup(gc, nic->ip));
229 }
230 if (nic->gatewaydev) {
231 flexarray_append(back, "gatewaydev");
232 flexarray_append(back, libxl__strdup(gc, nic->gatewaydev));
233 }
234
235 if (nic->rate_interval_usecs > 0) {
236 flexarray_append(back, "rate");
237 flexarray_append(back, GCSPRINTF("%"PRIu64",%"PRIu32"",
238 nic->rate_bytes_per_interval,
239 nic->rate_interval_usecs));
240 }
241
242 flexarray_append(back, "bridge");
243 flexarray_append(back, libxl__strdup(gc, nic->bridge));
244 flexarray_append(back, "handle");
245 flexarray_append(back, GCSPRINTF("%d", nic->devid));
246 flexarray_append(back, "type");
247 flexarray_append(back, libxl__strdup(gc,
248 libxl_nic_type_to_string(nic->nictype)));
249
250 flexarray_append(front, "handle");
251 flexarray_append(front, GCSPRINTF("%d", nic->devid));
252 flexarray_append(front, "mac");
253 flexarray_append(front, GCSPRINTF(
254 LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac)));
255
256 return 0;
257 }
258
libxl__device_nic_add(libxl__egc * egc,uint32_t domid,libxl_device_nic * nic,libxl__ao_device * aodev)259 static void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
260 libxl_device_nic *nic,
261 libxl__ao_device *aodev)
262 {
263 libxl__device_add_async(egc, domid, &libxl__nic_devtype, nic, aodev);
264 }
265
libxl__nic_from_xenstore(libxl__gc * gc,const char * libxl_path,libxl_devid devid,libxl_device_nic * nic)266 static int libxl__nic_from_xenstore(libxl__gc *gc, const char *libxl_path,
267 libxl_devid devid, libxl_device_nic *nic)
268 {
269 const char *tmp;
270 int rc;
271
272 libxl_device_nic_init(nic);
273
274 rc = libxl__xs_read_checked(gc, XBT_NULL,
275 GCSPRINTF("%s/handle", libxl_path), &tmp);
276 if (rc) goto out;
277 if (tmp)
278 nic->devid = atoi(tmp);
279 else
280 nic->devid = 0;
281
282 rc = libxl__xs_read_checked(gc, XBT_NULL,
283 GCSPRINTF("%s/backend", libxl_path), &tmp);
284 if (rc) goto out;
285
286 if (!tmp) {
287 LOG(ERROR, "nic %s does not exist (no backend path)", libxl_path);
288 rc = ERROR_FAIL;
289 goto out;
290 }
291 rc = libxl__backendpath_parse_domid(gc, tmp, &nic->backend_domid);
292 if (rc) goto out;
293
294 /* nic->mtu = */
295
296 rc = libxl__xs_read_checked(gc, XBT_NULL,
297 GCSPRINTF("%s/mac", libxl_path), &tmp);
298 if (rc) goto out;
299 if (tmp) {
300 rc = libxl__parse_mac(tmp, nic->mac);
301 if (rc) goto out;
302 } else {
303 memset(nic->mac, 0, sizeof(nic->mac));
304 }
305
306 rc = libxl__xs_read_checked(NOGC, XBT_NULL,
307 GCSPRINTF("%s/ip", libxl_path),
308 (const char **)(&nic->ip));
309 if (rc) goto out;
310 rc = libxl__xs_read_checked(NOGC, XBT_NULL,
311 GCSPRINTF("%s/bridge", libxl_path),
312 (const char **)(&nic->bridge));
313 if (rc) goto out;
314 rc = libxl__xs_read_checked(NOGC, XBT_NULL,
315 GCSPRINTF("%s/script", libxl_path),
316 (const char **)(&nic->script));
317 if (rc) goto out;
318 rc = libxl__xs_read_checked(NOGC, XBT_NULL,
319 GCSPRINTF("%s/forwarddev", libxl_path),
320 (const char **)(&nic->coloft_forwarddev));
321 if (rc) goto out;
322
323 #define CHECK_COLO_ARGS(arg) ({ \
324 rc = libxl__xs_read_checked(NOGC, XBT_NULL, \
325 GCSPRINTF("%s/colo_"#arg, libxl_path), \
326 (const char **)(&nic->colo_##arg)); \
327 if (rc) goto out; \
328 })
329
330 CHECK_COLO_ARGS(sock_mirror_id);
331 CHECK_COLO_ARGS(sock_mirror_ip);
332 CHECK_COLO_ARGS(sock_mirror_port);
333 CHECK_COLO_ARGS(sock_compare_pri_in_id);
334 CHECK_COLO_ARGS(sock_compare_pri_in_ip);
335 CHECK_COLO_ARGS(sock_compare_pri_in_port);
336 CHECK_COLO_ARGS(sock_compare_sec_in_id);
337 CHECK_COLO_ARGS(sock_compare_sec_in_ip);
338 CHECK_COLO_ARGS(sock_compare_sec_in_port);
339 CHECK_COLO_ARGS(sock_compare_notify_id);
340 CHECK_COLO_ARGS(sock_compare_notify_ip);
341 CHECK_COLO_ARGS(sock_compare_notify_port);
342 CHECK_COLO_ARGS(sock_redirector0_id);
343 CHECK_COLO_ARGS(sock_redirector0_ip);
344 CHECK_COLO_ARGS(sock_redirector0_port);
345 CHECK_COLO_ARGS(sock_redirector1_id);
346 CHECK_COLO_ARGS(sock_redirector1_ip);
347 CHECK_COLO_ARGS(sock_redirector1_port);
348 CHECK_COLO_ARGS(sock_redirector2_id);
349 CHECK_COLO_ARGS(sock_redirector2_ip);
350 CHECK_COLO_ARGS(sock_redirector2_port);
351 CHECK_COLO_ARGS(filter_mirror_queue);
352 CHECK_COLO_ARGS(filter_mirror_outdev);
353 CHECK_COLO_ARGS(filter_redirector0_queue);
354 CHECK_COLO_ARGS(filter_redirector0_indev);
355 CHECK_COLO_ARGS(filter_redirector0_outdev);
356 CHECK_COLO_ARGS(filter_redirector1_queue);
357 CHECK_COLO_ARGS(filter_redirector1_indev);
358 CHECK_COLO_ARGS(filter_redirector1_outdev);
359 CHECK_COLO_ARGS(compare_pri_in);
360 CHECK_COLO_ARGS(compare_sec_in);
361 CHECK_COLO_ARGS(compare_out);
362 CHECK_COLO_ARGS(compare_notify_dev);
363 CHECK_COLO_ARGS(sock_sec_redirector0_id);
364 CHECK_COLO_ARGS(sock_sec_redirector0_ip);
365 CHECK_COLO_ARGS(sock_sec_redirector0_port);
366 CHECK_COLO_ARGS(sock_sec_redirector1_id);
367 CHECK_COLO_ARGS(sock_sec_redirector1_ip);
368 CHECK_COLO_ARGS(sock_sec_redirector1_port);
369 CHECK_COLO_ARGS(filter_sec_redirector0_queue);
370 CHECK_COLO_ARGS(filter_sec_redirector0_indev);
371 CHECK_COLO_ARGS(filter_sec_redirector0_outdev);
372 CHECK_COLO_ARGS(filter_sec_redirector1_queue);
373 CHECK_COLO_ARGS(filter_sec_redirector1_indev);
374 CHECK_COLO_ARGS(filter_sec_redirector1_outdev);
375 CHECK_COLO_ARGS(filter_sec_rewriter0_queue);
376 CHECK_COLO_ARGS(checkpoint_host);
377 CHECK_COLO_ARGS(checkpoint_port);
378
379 #undef CHECK_COLO_ARGS
380
381 /* vif_ioemu nics use the same xenstore entries as vif interfaces */
382 rc = libxl__xs_read_checked(gc, XBT_NULL,
383 GCSPRINTF("%s/type", libxl_path), &tmp);
384 if (rc) goto out;
385 if (tmp) {
386 rc = libxl_nic_type_from_string(tmp, &nic->nictype);
387 if (rc) goto out;
388 } else {
389 nic->nictype = LIBXL_NIC_TYPE_VIF;
390 }
391 nic->model = NULL; /* XXX Only for TYPE_IOEMU */
392 nic->ifname = NULL; /* XXX Only for TYPE_IOEMU */
393
394 rc = 0;
395 out:
396 return rc;
397 }
398
libxl_devid_to_device_nic(libxl_ctx * ctx,uint32_t domid,int devid,libxl_device_nic * nic)399 int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
400 int devid, libxl_device_nic *nic)
401 {
402 GC_INIT(ctx);
403 char *libxl_dom_path, *libxl_path;
404 int rc = ERROR_FAIL;
405
406 libxl_device_nic_init(nic);
407 libxl_dom_path = libxl__xs_libxl_path(gc, domid);
408 if (!libxl_dom_path)
409 goto out;
410
411 libxl_path = GCSPRINTF("%s/device/vif/%d", libxl_dom_path, devid);
412
413 rc = libxl__nic_from_xenstore(gc, libxl_path, devid, nic);
414 if (rc) goto out;
415
416 rc = 0;
417 out:
418 GC_FREE;
419 return rc;
420 }
421
libxl_device_nic_list(libxl_ctx * ctx,uint32_t domid,int * num)422 libxl_device_nic *libxl_device_nic_list(libxl_ctx *ctx, uint32_t domid, int *num)
423 {
424 libxl_device_nic *r;
425
426 GC_INIT(ctx);
427
428 r = libxl__device_list(gc, &libxl__nic_devtype, domid, num);
429
430 GC_FREE;
431
432 return r;
433 }
434
libxl_device_nic_list_free(libxl_device_nic * list,int num)435 void libxl_device_nic_list_free(libxl_device_nic* list, int num)
436 {
437 libxl__device_list_free(&libxl__nic_devtype, list, num);
438 }
439
libxl_device_nic_getinfo(libxl_ctx * ctx,uint32_t domid,libxl_device_nic * nic,libxl_nicinfo * nicinfo)440 int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
441 libxl_device_nic *nic, libxl_nicinfo *nicinfo)
442 {
443 GC_INIT(ctx);
444 char *dompath, *nicpath, *libxl_path;
445 char *val;
446 int rc;
447
448 dompath = libxl__xs_get_dompath(gc, domid);
449 nicinfo->devid = nic->devid;
450
451 nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid);
452 libxl_path = GCSPRINTF("%s/device/vif/%d",
453 libxl__xs_libxl_path(gc, domid), nicinfo->devid);
454 nicinfo->backend = xs_read(ctx->xsh, XBT_NULL,
455 GCSPRINTF("%s/backend", libxl_path), NULL);
456 if (!nicinfo->backend) {
457 GC_FREE;
458 return ERROR_FAIL;
459 }
460 rc = libxl__backendpath_parse_domid(gc, nicinfo->backend,
461 &nicinfo->backend_id);
462 if (rc) goto out;
463
464 val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath));
465 nicinfo->state = val ? strtoul(val, NULL, 10) : -1;
466 val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", nicpath));
467 nicinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
468 val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tx-ring-ref", nicpath));
469 nicinfo->rref_tx = val ? strtoul(val, NULL, 10) : -1;
470 val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/rx-ring-ref", nicpath));
471 nicinfo->rref_rx = val ? strtoul(val, NULL, 10) : -1;
472 nicinfo->frontend = libxl__strdup(NOGC, nicpath);
473 nicinfo->frontend_id = domid;
474
475 rc = 0;
476 out:
477 GC_FREE;
478 return rc;
479 }
480
libxl__device_nic_devname(libxl__gc * gc,uint32_t domid,uint32_t devid,libxl_nic_type type)481 const char *libxl__device_nic_devname(libxl__gc *gc,
482 uint32_t domid,
483 uint32_t devid,
484 libxl_nic_type type)
485 {
486 switch (type) {
487 case LIBXL_NIC_TYPE_VIF:
488 return GCSPRINTF(NETBACK_NIC_NAME, domid, devid);
489 case LIBXL_NIC_TYPE_VIF_IOEMU:
490 return GCSPRINTF(NETBACK_NIC_NAME TAP_DEVICE_SUFFIX, domid, devid);
491 default:
492 abort();
493 }
494 }
495
libxl_device_nic_compare(libxl_device_nic * d1,libxl_device_nic * d2)496 static int libxl_device_nic_compare(libxl_device_nic *d1,
497 libxl_device_nic *d2)
498 {
499 return COMPARE_DEVID(d1, d2);
500 }
501
libxl_device_nic_update_config(libxl__gc * gc,void * d,void * s)502 static void libxl_device_nic_update_config(libxl__gc *gc, void *d, void *s)
503 {
504 libxl__update_config_nic(gc, d, s);
505 }
506
libxl__device_nic_set_devids(libxl__gc * gc,libxl_domain_config * d_config,uint32_t domid)507 int libxl__device_nic_set_devids(libxl__gc *gc, libxl_domain_config *d_config,
508 uint32_t domid)
509 {
510 int ret = 0;
511 int i;
512 size_t last_devid = -1;
513
514 for (i = 0; i < d_config->num_nics; i++) {
515 /* We have to init the nic here, because we still haven't
516 * called libxl_device_nic_add when domcreate_launch_dm gets called,
517 * but qemu needs the nic information to be complete.
518 */
519 ret = libxl__device_nic_setdefault(gc, domid, &d_config->nics[i],
520 false);
521 if (ret) {
522 LOGD(ERROR, domid, "Unable to set nic defaults for nic %d", i);
523 goto out;
524 }
525
526 if (d_config->nics[i].devid > last_devid)
527 last_devid = d_config->nics[i].devid;
528 }
529 for (i = 0; i < d_config->num_nics; i++) {
530 if (d_config->nics[i].devid < 0)
531 d_config->nics[i].devid = ++last_devid;
532 }
533
534 out:
535 return ret;
536 }
537
538 LIBXL_DEFINE_DEVICE_ADD(nic)
539 LIBXL_DEFINE_DEVICES_ADD(nic)
540 LIBXL_DEFINE_DEVICE_REMOVE(nic)
541
542 DEFINE_DEVICE_TYPE_STRUCT_X(nic, nic, vif,
543 .update_config = libxl_device_nic_update_config,
544 .from_xenstore = (device_from_xenstore_fn_t)libxl__nic_from_xenstore,
545 .set_xenstore_config = (device_set_xenstore_config_fn_t)
546 libxl__set_xenstore_nic,
547 );
548
549 /*
550 * Local variables:
551 * mode: C
552 * c-basic-offset: 4
553 * indent-tabs-mode: nil
554 * End:
555 */
556