bridge.c 22.9 KB
Newer Older
1
/*
2
 * Copyright (C) 2007, 2009, 2011 Red Hat, Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 * Authors:
 *     Mark McLoughlin <markmc@redhat.com>
 */

#include <config.h>

24
#if defined(WITH_BRIDGE)
25

26
# include "bridge.h"
E
Eric Blake 已提交
27
# include "virfile.h"
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <unistd.h>
# include <fcntl.h>
# include <errno.h>
# include <arpa/inet.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <sys/ioctl.h>
# include <paths.h>
# include <sys/wait.h>

# include <linux/param.h>     /* HZ                 */
# include <linux/sockios.h>   /* SIOCBRADDBR etc.   */
# include <linux/if_bridge.h> /* SYSFS_BRIDGE_ATTR  */
# include <linux/if_tun.h>    /* IFF_TUN, IFF_NO_PI */
# include <net/if_arp.h>    /* ARPHRD_ETHER */

# include "internal.h"
49
# include "command.h"
50 51 52
# include "memory.h"
# include "util.h"
# include "logging.h"
53
# include "network.h"
54
# include "virterror_internal.h"
55 56 57

# define JIFFIES_TO_MS(j) (((j)*1000)/HZ)
# define MS_TO_JIFFIES(ms) (((ms)*HZ)/1000)
58

59
# define VIR_FROM_THIS VIR_FROM_NONE
60

61 62 63 64
static int virNetDevSetupControlFull(const char *ifname,
                                     struct ifreq *ifr,
                                     int domain,
                                     int type)
65 66 67
{
    int fd;

D
Daniel P. Berrange 已提交
68 69
    if (ifname && ifr) {
        memset(ifr, 0, sizeof(*ifr));
70

D
Daniel P. Berrange 已提交
71
        if (virStrcpyStatic(ifr->ifr_name, ifname) == NULL) {
72 73 74
            virReportSystemError(ERANGE,
                                 _("Network interface name '%s' is too long"),
                                 ifname);
D
Daniel P. Berrange 已提交
75 76
            return -1;
        }
77
    }
78

79 80 81
    if ((fd = socket(domain, type, 0)) < 0) {
        virReportSystemError(errno, "%s",
                             _("Cannot open network interface control socket"));
D
Daniel P. Berrange 已提交
82
        return -1;
83
    }
84

D
Daniel P. Berrange 已提交
85
    if (virSetInherit(fd, false) < 0) {
86 87
        virReportSystemError(errno, "%s",
                             _("Cannot set close-on-exec flag for socket"));
D
Daniel P. Berrange 已提交
88 89 90
        VIR_FORCE_CLOSE(fd);
        return -1;
    }
91

D
Daniel P. Berrange 已提交
92 93
    return fd;
}
94 95


96 97
static int virNetDevSetupControl(const char *ifname,
                                 struct ifreq *ifr)
D
Daniel P. Berrange 已提交
98
{
99
    return virNetDevSetupControlFull(ifname, ifr, AF_PACKET, SOCK_DGRAM);
100 101
}

D
Daniel P. Berrange 已提交
102

103
/**
104
 * virNetDevBridgeCreate:
D
Daniel P. Berrange 已提交
105
 * @brname: the bridge name
106
 *
107
 * This function register a new bridge
108
 *
109
 * Returns 0 in case of success or -1 on failure
110
 */
111
# ifdef SIOCBRADDBR
112
int virNetDevBridgeCreate(const char *brname)
113
{
D
Daniel P. Berrange 已提交
114 115
    int fd = -1;
    int ret = -1;
116

117
    if ((fd = virNetDevSetupControl(NULL, NULL)) < 0)
118
        return -1;
119

D
Daniel P. Berrange 已提交
120
    if (ioctl(fd, SIOCBRADDBR, brname) < 0) {
121 122
        virReportSystemError(errno,
                             _("Unable to create bridge %s"), brname);
D
Daniel P. Berrange 已提交
123 124 125 126 127 128 129 130
        goto cleanup;
    }

    ret = 0;

cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
131
}
132
# else
133
int virNetDevBridgeCreate(const char *brname)
134
{
135 136 137
    virReportSystemError(ENOSYS,
                         _("Unable to create bridge %s"), brname);
    return -1;
138
}
139
# endif
140

141
# ifdef SIOCBRDELBR
142
/**
143 144
 * virNetDevExists:
 * @ifname
145
 *
146
 * Check if the network device @ifname exists
147 148 149
 *
 * Returns 1 if it exists, 0 if it does not, -1 on error
 */
150
int virNetDevExists(const char *ifname)
151
{
D
Daniel P. Berrange 已提交
152 153
    int fd = -1;
    int ret = -1;
154 155
    struct ifreq ifr;

156
    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
157
        return -1;
C
Chris Lalancette 已提交
158

159 160 161 162 163
    if (ioctl(fd, SIOCGIFFLAGS, &ifr)) {
        if (errno == ENODEV)
            ret = 0;
        else
            virReportSystemError(errno,
164
                                 _("Unable to check interface flags for %s"), ifname);
D
Daniel P. Berrange 已提交
165
        goto cleanup;
166
    }
167

168
    ret = 1;
169

D
Daniel P. Berrange 已提交
170 171 172
cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
173
}
174
# else
175
int virNetDevExists(const char *ifname)
176
{
177
    virReportSystemError(ENOSYS,
178
                         _("Unable to check interface %s"), ifname);
179
    return -1;
180
}
181
# endif
182

183
/**
184
 * virNetDevBridgeDelete:
D
Daniel P. Berrange 已提交
185
 * @brname: the bridge name
186 187 188 189 190
 *
 * Remove a bridge from the layer.
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
191
# ifdef SIOCBRDELBR
192
int virNetDevBridgeDelete(const char *brname)
193
{
D
Daniel P. Berrange 已提交
194 195 196
    int fd = -1;
    int ret = -1;

197
    if ((fd = virNetDevSetupControl(NULL, NULL)) < 0)
198
        return -1;
199

D
Daniel P. Berrange 已提交
200
    if (ioctl(fd, SIOCBRDELBR, brname) < 0) {
201 202
        virReportSystemError(errno,
                             _("Unable to delete bridge %s"), brname);
D
Daniel P. Berrange 已提交
203 204 205 206 207 208 209 210
        goto cleanup;
    }

    ret = 0;

cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
211
}
212
# else
213
int virNetDevBridgeDelete(const char *brname ATTRIBUTE_UNUSED)
214
{
215 216 217
    virReportSystemError(ENOSYS,
                         _("Unable to delete bridge %s"), brname);
    return -1;
218
}
219
# endif
220

221
/**
222
 * virNetDevBridgeAddPort:
D
Daniel P. Berrange 已提交
223 224
 * @brname: the bridge name
 * @ifname: the network interface name
225
 *
226 227 228 229
 * Adds an interface to a bridge
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
230
# ifdef SIOCBRADDIF
231 232
int virNetDevBridgeAddPort(const char *brname,
                           const char *ifname)
233
{
D
Daniel P. Berrange 已提交
234 235 236 237
    int fd = -1;
    int ret = -1;
    struct ifreq ifr;

238
    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
239
        return -1;
D
Daniel P. Berrange 已提交
240 241

    if (!(ifr.ifr_ifindex = if_nametoindex(ifname))) {
242 243
        virReportSystemError(ENODEV,
                             _("Unable to get interface index for %s"), ifname);
D
Daniel P. Berrange 已提交
244 245 246 247
        goto cleanup;
    }

    if (ioctl(fd, SIOCBRADDIF, &ifr) < 0) {
248 249
        virReportSystemError(errno,
                             _("Unable to add bridge %s port %s"), brname, ifname);
D
Daniel P. Berrange 已提交
250 251 252 253 254 255 256
        goto cleanup;
    }

    ret = 0;
cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
257
}
258
# else
259 260
int virNetDevBridgeAddPort(const char *brname,
                           const char *ifname)
261
{
262 263 264
    virReportSystemError(ENOSYS,
                         _("Unable to add bridge %s port %s"), brname, ifname);
    return -1;
265
}
266
# endif
267

268
/**
269
 * virNetDevBridgeRemovePort:
D
Daniel P. Berrange 已提交
270 271
 * @brname: the bridge name
 * @ifname: the network interface name
272
 *
273 274 275 276
 * Removes an interface from a bridge
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
277
# ifdef SIOCBRDELIF
278 279
int virNetDevBridgeRemovePort(const char *brname,
                              const char *ifname)
280
{
D
Daniel P. Berrange 已提交
281 282 283 284
    int fd = -1;
    int ret = -1;
    struct ifreq ifr;

285
    if ((fd = virNetDevSetupControl(brname, &ifr)) < 0)
286
        return -1;
D
Daniel P. Berrange 已提交
287 288

    if (!(ifr.ifr_ifindex = if_nametoindex(ifname))) {
289 290 291
        virReportSystemError(ENODEV,
                             _("Unable to get interface index for %s"), ifname);

D
Daniel P. Berrange 已提交
292 293 294 295
        goto cleanup;
    }

    if (ioctl(fd, SIOCBRDELIF, &ifr) < 0) {
296 297
        virReportSystemError(errno,
                             _("Unable to remove bridge %s port %s"), brname, ifname);
D
Daniel P. Berrange 已提交
298 299 300 301 302 303 304
        goto cleanup;
    }

    ret = 0;
cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
305
}
306
# else
307 308
int virNetDevBridgeRemovePort(const char *brname,
                              const char *ifname)
309
{
310 311 312
    virReportSystemError(errno,
                         _("Unable to remove bridge %s port %s"), brname, ifname);
    return -1;
313
}
314
# endif
315

316
/**
317
 * virNetDevSetMAC:
318 319 320 321 322 323
 * @ifname: interface name to set MTU for
 * @macaddr: MAC address (VIR_MAC_BUFLEN in size)
 *
 * This function sets the @macaddr for a given interface @ifname. This
 * gets rid of the kernel's automatically assigned random MAC.
 *
324
 * Returns 0 in case of success or -1 on failure
325
 */
326 327
int virNetDevSetMAC(const char *ifname,
                    const unsigned char *macaddr)
328
{
D
Daniel P. Berrange 已提交
329 330
    int fd = -1;
    int ret = -1;
331 332
    struct ifreq ifr;

333
    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
334
        return -1;
335 336

    /* To fill ifr.ifr_hdaddr.sa_family field */
D
Daniel P. Berrange 已提交
337
    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
338 339 340
        virReportSystemError(errno,
                             _("Cannot get interface MAC on '%s'"),
                             ifname);
D
Daniel P. Berrange 已提交
341 342
        goto cleanup;
    }
343 344 345

    memcpy(ifr.ifr_hwaddr.sa_data, macaddr, VIR_MAC_BUFLEN);

D
Daniel P. Berrange 已提交
346
    if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) {
347 348 349
        virReportSystemError(errno,
                             _("Cannot set interface MAC on '%s'"),
                             ifname);
D
Daniel P. Berrange 已提交
350 351 352 353 354 355 356 357
        goto cleanup;
    }

    ret = 0;

cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
358 359
}

360
/**
361
 * virNetDevGetMTU:
362 363 364 365
 * @ifname: interface name get MTU for
 *
 * This function gets the @mtu value set for a given interface @ifname.
 *
366
 * Returns the MTU value in case of success, or -1 on failure.
367
 */
D
Daniel P. Berrange 已提交
368
int virNetDevGetMTU(const char *ifname)
369
{
D
Daniel P. Berrange 已提交
370 371
    int fd = -1;
    int ret = -1;
372 373
    struct ifreq ifr;

374
    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
375 376
        return -1;

377 378 379 380
    if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) {
        virReportSystemError(errno,
                             _("Cannot get interface MTU on '%s'"),
                             ifname);
D
Daniel P. Berrange 已提交
381
        goto cleanup;
382
    }
383

D
Daniel P. Berrange 已提交
384
    ret = ifr.ifr_mtu;
385

D
Daniel P. Berrange 已提交
386 387 388
cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
389 390 391
}

/**
392
 * virNetDevSetMTU:
393 394 395 396 397 398
 * @ifname: interface name to set MTU for
 * @mtu: MTU value
 *
 * This function sets the @mtu for a given interface @ifname.  Typically
 * used on a tap device to set up for Jumbo Frames.
 *
399
 * Returns 0 in case of success, or -1 on failure
400
 */
D
Daniel P. Berrange 已提交
401
int virNetDevSetMTU(const char *ifname, int mtu)
402
{
D
Daniel P. Berrange 已提交
403 404
    int fd = -1;
    int ret = -1;
405 406
    struct ifreq ifr;

407
    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
408
        return -1;
409 410 411

    ifr.ifr_mtu = mtu;

D
Daniel P. Berrange 已提交
412
    if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) {
413 414 415
        virReportSystemError(errno,
                             _("Cannot set interface MTU on '%s'"),
                             ifname);
D
Daniel P. Berrange 已提交
416 417 418 419 420 421 422 423
        goto cleanup;
    }

    ret = 0;

cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
424 425 426
}

/**
D
Daniel P. Berrange 已提交
427
 * virNetDevSetMTUFromDevice:
428
 * @ifname: name of the interface whose MTU we want to set
D
Daniel P. Berrange 已提交
429
 * @otherifname: name of the interface whose MTU we want to copy
430
 *
D
Daniel P. Berrange 已提交
431
 * Sets the interface mtu to the same MTU as another interface
432
 *
433
 * Returns 0 in case of success, or -1 on failure
434
 */
D
Daniel P. Berrange 已提交
435 436
int virNetDevSetMTUFromDevice(const char *ifname,
                              const char *otherifname)
437
{
D
Daniel P. Berrange 已提交
438
    int mtu = virNetDevGetMTU(otherifname);
439 440

    if (mtu < 0)
441
        return -1;
442

443
    return virNetDevSetMTU(ifname, mtu);
444 445
}

446
/**
447
 * virNetDevProbeVnetHdr:
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
 * @tapfd: a tun/tap file descriptor
 *
 * Check whether it is safe to enable the IFF_VNET_HDR flag on the
 * tap interface.
 *
 * Setting IFF_VNET_HDR enables QEMU's virtio_net driver to allow
 * guests to pass larger (GSO) packets, with partial checksums, to
 * the host. This greatly increases the achievable throughput.
 *
 * It is only useful to enable this when we're setting up a virtio
 * interface. And it is only *safe* to enable it when we know for
 * sure that a) qemu has support for IFF_VNET_HDR and b) the running
 * kernel implements the TUNGETIFF ioctl(), which qemu needs to query
 * the supplied tapfd.
 *
463
 * Returns 1 if VnetHdr is supported, 0 if not supported
464
 */
465
# ifdef IFF_VNET_HDR
466
static int
467
virNetDevProbeVnetHdr(int tapfd)
468
{
469
#  if defined(IFF_VNET_HDR) && defined(TUNGETFEATURES) && defined(TUNGETIFF)
470 471 472 473
    unsigned int features;
    struct ifreq dummy;

    if (ioctl(tapfd, TUNGETFEATURES, &features) != 0) {
474 475
        VIR_INFO("Not enabling IFF_VNET_HDR; "
                 "TUNGETFEATURES ioctl() not implemented");
476 477 478 479
        return 0;
    }

    if (!(features & IFF_VNET_HDR)) {
480 481
        VIR_INFO("Not enabling IFF_VNET_HDR; "
                 "TUNGETFEATURES ioctl() reports no IFF_VNET_HDR");
482 483 484 485 486 487 488
        return 0;
    }

    /* The kernel will always return -1 at this point.
     * If TUNGETIFF is not implemented then errno == EBADFD.
     */
    if (ioctl(tapfd, TUNGETIFF, &dummy) != -1 || errno != EBADFD) {
489 490
        VIR_INFO("Not enabling IFF_VNET_HDR; "
                 "TUNGETIFF ioctl() not implemented");
491 492 493
        return 0;
    }

494
    VIR_INFO("Enabling IFF_VNET_HDR");
495 496

    return 1;
497
#  else
498
    (void) tapfd;
499
    VIR_INFO("Not enabling IFF_VNET_HDR; disabled at build time");
500
    return 0;
501
#  endif
502
}
503
# endif
504

505 506
/**
 * brAddTap:
D
Daniel P. Berrange 已提交
507
 * @brname: the bridge name
508
 * @ifname: the interface name (or name template)
509
 * @macaddr: desired MAC address (VIR_MAC_BUFLEN long)
510
 * @vnet_hdr: whether to try enabling IFF_VNET_HDR
511 512
 * @tapfd: file descriptor return value for the new tap device
 *
D
typo  
Daniel Veillard 已提交
513
 * This function creates a new tap device on a bridge. @ifname can be either
514
 * a fixed name or a name template with '%d' for dynamic name allocation.
515 516 517 518 519
 * in either case the final name for the bridge will be stored in @ifname.
 * If the @tapfd parameter is supplied, the open tap device file
 * descriptor will be returned, otherwise the TAP device will be made
 * persistent and closed. The caller must use brDeleteTap to remove
 * a persistent TAP devices when it is no longer needed.
520
 *
521
 * Returns 0 in case of success or -1 on failure
522
 */
523 524 525 526 527 528
int virNetDevTapCreateInBridgePort(const char *brname,
                                   char **ifname,
                                   const unsigned char *macaddr,
                                   int vnet_hdr,
                                   bool up,
                                   int *tapfd)
529
{
530
    if (virNetDevTapCreate(ifname, vnet_hdr, tapfd) < 0)
531
        return -1;
C
Chris Lalancette 已提交
532

533 534 535 536 537 538
    /* We need to set the interface MAC before adding it
     * to the bridge, because the bridge assumes the lowest
     * MAC of all enslaved interfaces & we don't want it
     * seeing the kernel allocate random MAC for the TAP
     * device before we set our static MAC.
     */
539
    if (virNetDevSetMAC(*ifname, macaddr) < 0)
540 541
        goto error;

542 543 544 545
    /* We need to set the interface MTU before adding it
     * to the bridge, because the bridge will have its
     * MTU adjusted automatically when we add the new interface.
     */
D
Daniel P. Berrange 已提交
546
    if (virNetDevSetMTUFromDevice(*ifname, brname) < 0)
547 548
        goto error;

549
    if (virNetDevBridgeAddPort(brname, *ifname) < 0)
550 551
        goto error;

552
    if (virNetDevSetOnline(*ifname, up) < 0)
553
        goto error;
D
Daniel P. Berrange 已提交
554

555
    return 0;
556

557
error:
W
Wen Congyang 已提交
558 559
    if (tapfd)
        VIR_FORCE_CLOSE(*tapfd);
560
    return -1;
561 562
}

563
int virNetDevTapDelete(const char *ifname)
564 565 566
{
    struct ifreq try;
    int fd;
567
    int ret = -1;
568

569 570 571 572 573
    if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to open /dev/net/tun, is tun module loaded?"));
        return -1;
    }
574 575 576 577

    memset(&try, 0, sizeof(struct ifreq));
    try.ifr_flags = IFF_TAP|IFF_NO_PI;

C
Chris Lalancette 已提交
578
    if (virStrcpyStatic(try.ifr_name, ifname) == NULL) {
579 580 581 582
        virReportSystemError(ERANGE,
                             _("Network interface name '%s' is too long"),
                             ifname);
        goto cleanup;
583 584
    }

585 586 587 588
    if (ioctl(fd, TUNSETIFF, &try) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to associate TAP device"));
        goto cleanup;
589 590
    }

591 592 593 594 595
    if (ioctl(fd, TUNSETPERSIST, 0) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to make TAP device non-persistent"));
        goto cleanup;
    }
596

597 598 599 600 601
    ret = 0;

cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
602 603 604
}


605
/**
606
 * virNetDevSetOnline:
607
 * @ifname: the interface name
608
 * @online: true for up, false for down
609
 *
610
 * Function to control if an interface is activated (up, true) or not (down, false)
611
 *
612
 * Returns 0 in case of success or -1 on error.
613
 */
614
int virNetDevSetOnline(const char *ifname,
615
                       bool online)
616
{
D
Daniel P. Berrange 已提交
617 618
    int fd = -1;
    int ret = -1;
619
    struct ifreq ifr;
E
Eric Blake 已提交
620
    int ifflags;
621

622
    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
623
        return -1;
624

D
Daniel P. Berrange 已提交
625
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
626 627 628
        virReportSystemError(errno,
                             _("Cannot get interface flags on '%s'"),
                             ifname);
D
Daniel P. Berrange 已提交
629 630 631
        goto cleanup;
    }

632
    if (online)
D
Daniel P. Berrange 已提交
633 634 635
        ifflags = ifr.ifr_flags | IFF_UP;
    else
        ifflags = ifr.ifr_flags & ~IFF_UP;
636

E
Eric Blake 已提交
637 638
    if (ifr.ifr_flags != ifflags) {
        ifr.ifr_flags = ifflags;
D
Daniel P. Berrange 已提交
639
        if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
640 641 642
            virReportSystemError(errno,
                                 _("Cannot set interface flags on '%s'"),
                                 ifname);
D
Daniel P. Berrange 已提交
643 644
            goto cleanup;
        }
645 646
    }

D
Daniel P. Berrange 已提交
647 648 649 650 651
    ret = 0;

cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
652 653
}

654
/**
655
 * virNetDevIsOnline:
656
 * @ifname: the interface name
657
 * @online: where to store the status
658
 *
659
 * Function to query if an interface is activated (true) or not (false)
660 661 662
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
663
int virNetDevIsOnline(const char *ifname,
664
                      bool *online)
665
{
D
Daniel P. Berrange 已提交
666 667
    int fd = -1;
    int ret = -1;
668 669
    struct ifreq ifr;

670
    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
671
        return -1;
672

D
Daniel P. Berrange 已提交
673
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
674 675 676
        virReportSystemError(errno,
                             _("Cannot get interface flags on '%s'"),
                             ifname);
D
Daniel P. Berrange 已提交
677 678 679
        goto cleanup;
    }

680
    *online = (ifr.ifr_flags & IFF_UP) ? true : false;
D
Daniel P. Berrange 已提交
681
    ret = 0;
682

D
Daniel P. Berrange 已提交
683 684 685
cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
686 687
}

688
/**
689
 * virNetDevSetIPv4Address:
690
 * @ifname: the interface name
691 692
 * @addr: the IP address (IPv4 or IPv6)
 * @prefix: number of 1 bits in the netmask
693
 *
694 695 696
 * Add an IP address to an interface. This function *does not* remove
 * any previously added IP addresses - that must be done separately with
 * brDelInetAddress.
697
 *
698
 * Returns 0 in case of success or -1 in case of error.
699 700
 */

701 702 703
int virNetDevSetIPv4Address(const char *ifname,
                            virSocketAddr *addr,
                            unsigned int prefix)
704
{
J
Jiri Denemark 已提交
705
    virCommandPtr cmd = NULL;
706 707
    char *addrstr = NULL, *bcaststr = NULL;
    virSocketAddr broadcast;
708 709 710 711
    int ret = -1;

    if (!(addrstr = virSocketFormatAddr(addr)))
        goto cleanup;
712 713 714 715 716 717
    /* format up a broadcast address if this is IPv4 */
    if ((VIR_SOCKET_IS_FAMILY(addr, AF_INET)) &&
        ((virSocketAddrBroadcastByPrefix(addr, prefix, &broadcast) < 0) ||
         !(bcaststr = virSocketFormatAddr(&broadcast)))) {
        goto cleanup;
    }
718 719 720
    cmd = virCommandNew(IP_PATH);
    virCommandAddArgList(cmd, "addr", "add", NULL);
    virCommandAddArgFormat(cmd, "%s/%u", addrstr, prefix);
721 722
    if (bcaststr)
        virCommandAddArgList(cmd, "broadcast", bcaststr, NULL);
723 724 725 726 727 728 729 730
    virCommandAddArgList(cmd, "dev", ifname, NULL);

    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    ret = 0;
cleanup:
    VIR_FREE(addrstr);
731
    VIR_FREE(bcaststr);
732 733
    virCommandFree(cmd);
    return ret;
734 735
}

736
/**
737
 * virNetDevClearIPv4Address:
738
 * @ifname: the interface name
739 740
 * @addr: the IP address (IPv4 or IPv6)
 * @prefix: number of 1 bits in the netmask
741
 *
742
 * Delete an IP address from an interface.
743
 *
744
 * Returns 0 in case of success or -1 in case of error.
745 746
 */

747 748 749
int virNetDevClearIPv4Address(const char *ifname,
                              virSocketAddr *addr,
                              unsigned int prefix)
750
{
J
Jiri Denemark 已提交
751
    virCommandPtr cmd = NULL;
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
    char *addrstr;
    int ret = -1;

    if (!(addrstr = virSocketFormatAddr(addr)))
        goto cleanup;
    cmd = virCommandNew(IP_PATH);
    virCommandAddArgList(cmd, "addr", "del", NULL);
    virCommandAddArgFormat(cmd, "%s/%u", addrstr, prefix);
    virCommandAddArgList(cmd, "dev", ifname, NULL);

    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    ret = 0;
cleanup:
    VIR_FREE(addrstr);
    virCommandFree(cmd);
    return ret;
770 771
}

772
/**
773
 * virNetDevBridgeSetSTPDelay:
D
Daniel P. Berrange 已提交
774
 * @brname: the bridge name
775 776 777 778
 * @delay: delay in seconds
 *
 * Set the bridge forward delay
 *
779
 * Returns 0 in case of success or -1 on failure
780
 */
781

782 783
int virNetDevBridgeSetSTPDelay(const char *brname,
                               int delay)
784
{
785 786
    virCommandPtr cmd;
    int ret = -1;
787

788
    cmd = virCommandNew(BRCTL);
D
Daniel P. Berrange 已提交
789
    virCommandAddArgList(cmd, "setfd", brname, NULL);
790
    virCommandAddArgFormat(cmd, "%d", delay);
791

792 793
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;
794

795 796 797 798
    ret = 0;
cleanup:
    virCommandFree(cmd);
    return ret;
799 800
}

801
/**
802
 * virNetDevBridgeSetSTP:
D
Daniel P. Berrange 已提交
803
 * @brname: the bridge name
804 805 806 807 808
 * @enable: 1 to enable, 0 to disable
 *
 * Control whether the bridge participates in the spanning tree protocol,
 * in general don't disable it without good reasons.
 *
809
 * Returns 0 in case of success or -1 on failure
810
 */
811
int virNetDevBridgeSetSTP(const char *brname,
812
                          bool enable)
813
{
814 815
    virCommandPtr cmd;
    int ret = -1;
816

817
    cmd = virCommandNew(BRCTL);
D
Daniel P. Berrange 已提交
818
    virCommandAddArgList(cmd, "stp", brname,
819 820
                         enable ? "on" : "off",
                         NULL);
821

822 823 824 825 826 827 828
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    ret = 0;
cleanup:
    virCommandFree(cmd);
    return ret;
829 830
}

831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
/**
 * brCreateTap:
 * @ifname: the interface name
 * @vnet_hr: whether to try enabling IFF_VNET_HDR
 * @tapfd: file descriptor return value for the new tap device
 *
 * Creates a tap interface.
 * If the @tapfd parameter is supplied, the open tap device file
 * descriptor will be returned, otherwise the TAP device will be made
 * persistent and closed. The caller must use brDeleteTap to remove
 * a persistent TAP devices when it is no longer needed.
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */

846 847 848
int virNetDevTapCreate(char **ifname,
                       int vnet_hdr ATTRIBUTE_UNUSED,
                       int *tapfd)
849 850 851
{
    int fd;
    struct ifreq ifr;
852
    int ret = -1;
853

854 855 856 857 858
    if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to open /dev/net/tun, is tun module loaded?"));
        return -1;
    }
859 860 861 862 863 864

    memset(&ifr, 0, sizeof(ifr));

    ifr.ifr_flags = IFF_TAP|IFF_NO_PI;

# ifdef IFF_VNET_HDR
865
    if (vnet_hdr && virNetDevProbeVnetHdr(fd))
866 867 868 869
        ifr.ifr_flags |= IFF_VNET_HDR;
# endif

    if (virStrcpyStatic(ifr.ifr_name, *ifname) == NULL) {
870 871 872 873 874
        virReportSystemError(ERANGE,
                             _("Network interface name '%s' is too long"),
                             *ifname);
        goto cleanup;

875 876
    }

877 878 879 880 881 882
    if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
        virReportSystemError(errno,
                             _("Unable to create tap device %s"),
                             NULLSTR(*ifname));
        goto cleanup;
    }
883 884

    if (!tapfd &&
885 886 887 888 889 890 891
        (errno = ioctl(fd, TUNSETPERSIST, 1))) {
        virReportSystemError(errno,
                             _("Unable to set tap device %s to persistent"),
                             NULLSTR(*ifname));
        goto cleanup;
    }

892
    VIR_FREE(*ifname);
893 894 895 896 897
    if (!(*ifname = strdup(ifr.ifr_name))) {
        virReportOOMError();
        goto cleanup;
    }
    if (tapfd)
898 899 900 901
        *tapfd = fd;
    else
        VIR_FORCE_CLOSE(fd);

902
    ret = 0;
903

904 905 906 907 908
cleanup:
    if (ret < 0)
        VIR_FORCE_CLOSE(fd);

    return ret;
909 910
}

911
#endif /* WITH_BRIDGE */