bridge.c 18.6 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 55 56

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


D
Daniel P. Berrange 已提交
59 60 61 62
static int brSetupControlFull(const char *ifname,
                              struct ifreq *ifr,
                              int domain,
                              int type)
63 64 65
{
    int fd;

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

D
Daniel P. Berrange 已提交
69 70 71 72
        if (virStrcpyStatic(ifr->ifr_name, ifname) == NULL) {
            errno = EINVAL;
            return -1;
        }
73
    }
74

D
Daniel P. Berrange 已提交
75 76
    if ((fd = socket(domain, type, 0)) < 0)
        return -1;
77

D
Daniel P. Berrange 已提交
78 79 80 81
    if (virSetInherit(fd, false) < 0) {
        VIR_FORCE_CLOSE(fd);
        return -1;
    }
82

D
Daniel P. Berrange 已提交
83 84
    return fd;
}
85 86


D
Daniel P. Berrange 已提交
87 88 89 90
static int brSetupControl(const char *ifname,
                          struct ifreq *ifr)
{
    return brSetupControlFull(ifname, ifr, AF_PACKET, SOCK_DGRAM);
91 92
}

D
Daniel P. Berrange 已提交
93

94 95
/**
 * brAddBridge:
D
Daniel P. Berrange 已提交
96
 * @brname: the bridge name
97
 *
98
 * This function register a new bridge
99 100 101
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
102
# ifdef SIOCBRADDBR
103
int
D
Daniel P. Berrange 已提交
104
brAddBridge(const char *brname)
105
{
D
Daniel P. Berrange 已提交
106 107
    int fd = -1;
    int ret = -1;
108

D
Daniel P. Berrange 已提交
109 110
    if ((fd = brSetupControl(NULL, NULL)) < 0)
        return errno;
111

D
Daniel P. Berrange 已提交
112 113 114 115 116 117 118 119 120 121
    if (ioctl(fd, SIOCBRADDBR, brname) < 0) {
        ret = errno;
        goto cleanup;
    }

    ret = 0;

cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
122
}
123
# else
D
Daniel P. Berrange 已提交
124
int brAddBridge (const char *brname ATTRIBUTE_UNUSED)
125 126 127
{
    return EINVAL;
}
128
# endif
129

130
# ifdef SIOCBRDELBR
131
int
D
Daniel P. Berrange 已提交
132
brHasBridge(const char *brname)
133
{
D
Daniel P. Berrange 已提交
134 135
    int fd = -1;
    int ret = -1;
136 137
    struct ifreq ifr;

D
Daniel P. Berrange 已提交
138 139
    if ((fd = brSetupControl(brname, &ifr)) < 0)
        return errno;
C
Chris Lalancette 已提交
140

D
Daniel P. Berrange 已提交
141 142
    if (ioctl(fd, SIOCGIFFLAGS, &ifr))
        goto cleanup;
143

D
Daniel P. Berrange 已提交
144
    ret = 0;
145

D
Daniel P. Berrange 已提交
146 147 148
cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
149
}
150
# else
151
int
D
Daniel P. Berrange 已提交
152
brHasBridge(const char *brname ATTRIBUTE_UNUSED)
153 154 155
{
    return EINVAL;
}
156
# endif
157

158 159
/**
 * brDeleteBridge:
D
Daniel P. Berrange 已提交
160
 * @brname: the bridge name
161 162 163 164 165
 *
 * Remove a bridge from the layer.
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
166
# ifdef SIOCBRDELBR
167
int
D
Daniel P. Berrange 已提交
168
brDeleteBridge(const char *brname)
169
{
D
Daniel P. Berrange 已提交
170 171 172 173 174
    int fd = -1;
    int ret = -1;

    if ((fd = brSetupControl(NULL, NULL)) < 0)
        return errno;
175

D
Daniel P. Berrange 已提交
176 177 178 179 180 181 182 183 184 185
    if (ioctl(fd, SIOCBRDELBR, brname) < 0) {
        ret = errno;
        goto cleanup;
    }

    ret = 0;

cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
186
}
187
# else
188
int
D
Daniel P. Berrange 已提交
189
brDeleteBridge(const char *brname ATTRIBUTE_UNUSED)
190 191 192
{
    return EINVAL;
}
193
# endif
194

195 196
/**
 * brAddInterface:
D
Daniel P. Berrange 已提交
197 198
 * @brname: the bridge name
 * @ifname: the network interface name
199
 *
200 201 202 203
 * Adds an interface to a bridge
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
204
# ifdef SIOCBRADDIF
205
int
D
Daniel P. Berrange 已提交
206 207
brAddInterface(const char *brname,
               const char *ifname)
208
{
D
Daniel P. Berrange 已提交
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
    int fd = -1;
    int ret = -1;
    struct ifreq ifr;

    if ((fd = brSetupControl(brname, &ifr)) < 0)
        return errno;

    if (!(ifr.ifr_ifindex = if_nametoindex(ifname))) {
        ret = errno;
        goto cleanup;
    }

    if (ioctl(fd, SIOCBRADDIF, &ifr) < 0) {
        ret = errno;
        goto cleanup;
    }

    ret = 0;
cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
230
}
231
# else
232
int
D
Daniel P. Berrange 已提交
233 234
brAddInterface(const char *brname ATTRIBUTE_UNUSED,
               const char *ifname ATTRIBUTE_UNUSED)
235 236 237
{
    return EINVAL;
}
238
# endif
239

240 241
/**
 * brDeleteInterface:
D
Daniel P. Berrange 已提交
242 243
 * @brname: the bridge name
 * @ifname: the network interface name
244
 *
245 246 247 248
 * Removes an interface from a bridge
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
249
# ifdef SIOCBRDELIF
250
int
D
Daniel P. Berrange 已提交
251 252
brDeleteInterface(const char *brname,
                  const char *ifname)
253
{
D
Daniel P. Berrange 已提交
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
    int fd = -1;
    int ret = -1;
    struct ifreq ifr;

    if ((fd = brSetupControl(brname, &ifr)) < 0)
        return errno;

    if (!(ifr.ifr_ifindex = if_nametoindex(ifname))) {
        ret = errno;
        goto cleanup;
    }

    if (ioctl(fd, SIOCBRDELIF, &ifr) < 0) {
        ret = errno;
        goto cleanup;
    }

    ret = 0;
cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
275
}
276
# else
277
int
D
Daniel P. Berrange 已提交
278 279
brDeleteInterface(const char *brname ATTRIBUTE_UNUSED,
                  const char *ifname ATTRIBUTE_UNUSED)
280 281 282
{
    return EINVAL;
}
283
# endif
284

285
/**
286
 * brSetInterfaceMac:
287 288 289 290 291 292 293 294
 * @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.
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
295
int
D
Daniel P. Berrange 已提交
296
brSetInterfaceMac(const char *ifname,
297
                  const unsigned char *macaddr)
298
{
D
Daniel P. Berrange 已提交
299 300
    int fd = -1;
    int ret = -1;
301 302
    struct ifreq ifr;

D
Daniel P. Berrange 已提交
303 304
    if ((fd = brSetupControl(ifname, &ifr)) < 0)
        return errno;
305 306

    /* To fill ifr.ifr_hdaddr.sa_family field */
D
Daniel P. Berrange 已提交
307 308 309 310
    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
        ret = errno;
        goto cleanup;
    }
311 312 313

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

D
Daniel P. Berrange 已提交
314 315 316 317 318 319 320 321 322 323
    if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) {
        ret = errno;
        goto cleanup;
    }

    ret = 0;

cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
324 325
}

326 327 328 329 330 331 332 333 334
/**
 * ifGetMtu
 * @ifname: interface name get MTU for
 *
 * This function gets the @mtu value set for a given interface @ifname.
 *
 * Returns the MTU value in case of success.
 * On error, returns -1 and sets errno accordingly
 */
D
Daniel P. Berrange 已提交
335
static int ifGetMtu(const char *ifname)
336
{
D
Daniel P. Berrange 已提交
337 338
    int fd = -1;
    int ret = -1;
339 340
    struct ifreq ifr;

D
Daniel P. Berrange 已提交
341
    if ((fd = brSetupControl(ifname, &ifr)) < 0)
342 343
        return -1;

D
Daniel P. Berrange 已提交
344 345
    if (ioctl(fd, SIOCGIFMTU, &ifr) < 0)
        goto cleanup;
346

D
Daniel P. Berrange 已提交
347
    ret = ifr.ifr_mtu;
348

D
Daniel P. Berrange 已提交
349 350 351
cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
352 353 354 355 356 357 358 359 360 361 362 363
}

/**
 * ifSetMtu:
 * @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.
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
D
Daniel P. Berrange 已提交
364
static int ifSetMtu(const char *ifname, int mtu)
365
{
D
Daniel P. Berrange 已提交
366 367
    int fd = -1;
    int ret = -1;
368 369
    struct ifreq ifr;

D
Daniel P. Berrange 已提交
370 371
    if ((fd = brSetupControl(ifname, &ifr)) < 0)
        return errno;
372 373 374

    ifr.ifr_mtu = mtu;

D
Daniel P. Berrange 已提交
375 376 377 378 379 380 381 382 383 384
    if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) {
        ret = errno;
        goto cleanup;
    }

    ret = 0;

cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
385 386 387 388
}

/**
 * brSetInterfaceMtu
D
Daniel P. Berrange 已提交
389
 * @brname: name of the bridge interface
390 391 392 393 394 395
 * @ifname: name of the interface whose MTU we want to set
 *
 * Sets the interface mtu to the same MTU of the bridge
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
D
Daniel P. Berrange 已提交
396
static int brSetInterfaceMtu(const char *brname,
397 398
                             const char *ifname)
{
D
Daniel P. Berrange 已提交
399
    int mtu = ifGetMtu(brname);
400 401 402 403

    if (mtu < 0)
        return errno;

D
Daniel P. Berrange 已提交
404
    return ifSetMtu(ifname, mtu);
405 406
}

407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
/**
 * brProbeVnetHdr:
 * @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.
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
426
# ifdef IFF_VNET_HDR
427 428 429
static int
brProbeVnetHdr(int tapfd)
{
430
#  if defined(IFF_VNET_HDR) && defined(TUNGETFEATURES) && defined(TUNGETIFF)
431 432 433 434
    unsigned int features;
    struct ifreq dummy;

    if (ioctl(tapfd, TUNGETFEATURES, &features) != 0) {
435 436
        VIR_INFO("Not enabling IFF_VNET_HDR; "
                 "TUNGETFEATURES ioctl() not implemented");
437 438 439 440
        return 0;
    }

    if (!(features & IFF_VNET_HDR)) {
441 442
        VIR_INFO("Not enabling IFF_VNET_HDR; "
                 "TUNGETFEATURES ioctl() reports no IFF_VNET_HDR");
443 444 445 446 447 448 449
        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) {
450 451
        VIR_INFO("Not enabling IFF_VNET_HDR; "
                 "TUNGETIFF ioctl() not implemented");
452 453 454
        return 0;
    }

455
    VIR_INFO("Enabling IFF_VNET_HDR");
456 457

    return 1;
458
#  else
459
    (void) tapfd;
460
    VIR_INFO("Not enabling IFF_VNET_HDR; disabled at build time");
461
    return 0;
462
#  endif
463
}
464
# endif
465

466 467
/**
 * brAddTap:
D
Daniel P. Berrange 已提交
468
 * @brname: the bridge name
469
 * @ifname: the interface name (or name template)
470
 * @macaddr: desired MAC address (VIR_MAC_BUFLEN long)
471
 * @vnet_hdr: whether to try enabling IFF_VNET_HDR
472 473
 * @tapfd: file descriptor return value for the new tap device
 *
D
typo  
Daniel Veillard 已提交
474
 * This function creates a new tap device on a bridge. @ifname can be either
475
 * a fixed name or a name template with '%d' for dynamic name allocation.
476 477 478 479 480
 * 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.
481 482 483
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
484
int
D
Daniel P. Berrange 已提交
485
brAddTap(const char *brname,
486
         char **ifname,
487
         const unsigned char *macaddr,
488
         int vnet_hdr,
489
         bool up,
490 491
         int *tapfd)
{
D
Daniel P. Berrange 已提交
492
    errno = brCreateTap(ifname, vnet_hdr, tapfd);
493

W
Wen Congyang 已提交
494 495
    /* fd has been closed in brCreateTap() when it failed. */
    if (errno)
C
Chris Lalancette 已提交
496 497
        goto error;

498 499 500 501 502 503
    /* 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.
     */
D
Daniel P. Berrange 已提交
504
    if ((errno = brSetInterfaceMac(*ifname, macaddr)))
W
Wen Congyang 已提交
505
        goto close_fd;
506 507 508 509
    /* 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 已提交
510
    if ((errno = brSetInterfaceMtu(brname, *ifname)))
W
Wen Congyang 已提交
511
        goto close_fd;
D
Daniel P. Berrange 已提交
512
    if ((errno = brAddInterface(brname, *ifname)))
W
Wen Congyang 已提交
513
        goto close_fd;
D
Daniel P. Berrange 已提交
514
    if (up && ((errno = brSetInterfaceUp(*ifname, 1))))
W
Wen Congyang 已提交
515
        goto close_fd;
D
Daniel P. Berrange 已提交
516

517
    return 0;
518

W
Wen Congyang 已提交
519 520 521 522
close_fd:
    if (tapfd)
        VIR_FORCE_CLOSE(*tapfd);
error:
523 524 525
    return errno;
}

D
Daniel P. Berrange 已提交
526
int brDeleteTap(const char *ifname)
527 528 529 530 531 532 533 534 535 536
{
    struct ifreq try;
    int fd;

    if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
        return errno;

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

C
Chris Lalancette 已提交
537
    if (virStrcpyStatic(try.ifr_name, ifname) == NULL) {
538 539 540 541 542 543 544 545 546 547
        errno = EINVAL;
        goto error;
    }

    if (ioctl(fd, TUNSETIFF, &try) == 0) {
        if ((errno = ioctl(fd, TUNSETPERSIST, 0)))
            goto error;
    }

 error:
548
    VIR_FORCE_CLOSE(fd);
549 550 551 552 553

    return errno;
}


554 555 556 557 558 559 560 561 562
/**
 * brSetInterfaceUp:
 * @ifname: the interface name
 * @up: 1 for up, 0 for down
 *
 * Function to control if an interface is activated (up, 1) or not (down, 0)
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
563
int
D
Daniel P. Berrange 已提交
564
brSetInterfaceUp(const char *ifname,
565 566
                 int up)
{
D
Daniel P. Berrange 已提交
567 568
    int fd = -1;
    int ret = -1;
569
    struct ifreq ifr;
E
Eric Blake 已提交
570
    int ifflags;
571

D
Daniel P. Berrange 已提交
572
    if ((fd = brSetupControl(ifname, &ifr)) < 0)
573 574
        return errno;

D
Daniel P. Berrange 已提交
575 576 577 578 579 580 581 582 583
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
        ret = errno;
        goto cleanup;
    }

    if (up)
        ifflags = ifr.ifr_flags | IFF_UP;
    else
        ifflags = ifr.ifr_flags & ~IFF_UP;
584

E
Eric Blake 已提交
585 586
    if (ifr.ifr_flags != ifflags) {
        ifr.ifr_flags = ifflags;
D
Daniel P. Berrange 已提交
587 588 589 590
        if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
            ret = errno;
            goto cleanup;
        }
591 592
    }

D
Daniel P. Berrange 已提交
593 594 595 596 597
    ret = 0;

cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
598 599
}

600 601 602 603 604 605 606 607 608
/**
 * brGetInterfaceUp:
 * @ifname: the interface name
 * @up: where to store the status
 *
 * Function to query if an interface is activated (1) or not (0)
 *
 * Returns 0 in case of success or an errno code in case of failure.
 */
609
int
D
Daniel P. Berrange 已提交
610
brGetInterfaceUp(const char *ifname,
611 612
                 int *up)
{
D
Daniel P. Berrange 已提交
613 614
    int fd = -1;
    int ret = -1;
615 616
    struct ifreq ifr;

D
Daniel P. Berrange 已提交
617
    if ((fd = brSetupControl(ifname, &ifr)) < 0)
618 619
        return errno;

D
Daniel P. Berrange 已提交
620 621 622 623 624
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
        ret = errno;
        goto cleanup;
    }

625
    *up = (ifr.ifr_flags & IFF_UP) ? 1 : 0;
D
Daniel P. Berrange 已提交
626
    ret = 0;
627

D
Daniel P. Berrange 已提交
628 629 630
cleanup:
    VIR_FORCE_CLOSE(fd);
    return ret;
631 632
}

633
/**
634
 * brAddInetAddress:
635
 * @ifname: the interface name
636 637
 * @addr: the IP address (IPv4 or IPv6)
 * @prefix: number of 1 bits in the netmask
638
 *
639 640 641
 * Add an IP address to an interface. This function *does not* remove
 * any previously added IP addresses - that must be done separately with
 * brDelInetAddress.
642
 *
643
 * Returns 0 in case of success or -1 in case of error.
644 645
 */

646
int
D
Daniel P. Berrange 已提交
647
brAddInetAddress(const char *ifname,
648 649
                 virSocketAddr *addr,
                 unsigned int prefix)
650
{
J
Jiri Denemark 已提交
651
    virCommandPtr cmd = NULL;
652 653
    char *addrstr = NULL, *bcaststr = NULL;
    virSocketAddr broadcast;
654 655 656 657
    int ret = -1;

    if (!(addrstr = virSocketFormatAddr(addr)))
        goto cleanup;
658 659 660 661 662 663
    /* 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;
    }
664 665 666
    cmd = virCommandNew(IP_PATH);
    virCommandAddArgList(cmd, "addr", "add", NULL);
    virCommandAddArgFormat(cmd, "%s/%u", addrstr, prefix);
667 668
    if (bcaststr)
        virCommandAddArgList(cmd, "broadcast", bcaststr, NULL);
669 670 671 672 673 674 675 676
    virCommandAddArgList(cmd, "dev", ifname, NULL);

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

    ret = 0;
cleanup:
    VIR_FREE(addrstr);
677
    VIR_FREE(bcaststr);
678 679
    virCommandFree(cmd);
    return ret;
680 681
}

682
/**
683
 * brDelInetAddress:
684
 * @ifname: the interface name
685 686
 * @addr: the IP address (IPv4 or IPv6)
 * @prefix: number of 1 bits in the netmask
687
 *
688
 * Delete an IP address from an interface.
689
 *
690
 * Returns 0 in case of success or -1 in case of error.
691 692
 */

693
int
D
Daniel P. Berrange 已提交
694
brDelInetAddress(const char *ifname,
695 696
                 virSocketAddr *addr,
                 unsigned int prefix)
697
{
J
Jiri Denemark 已提交
698
    virCommandPtr cmd = NULL;
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
    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;
717 718
}

719 720
/**
 * brSetForwardDelay:
D
Daniel P. Berrange 已提交
721
 * @brname: the bridge name
722 723 724 725
 * @delay: delay in seconds
 *
 * Set the bridge forward delay
 *
726
 * Returns 0 in case of success or -1 on failure
727
 */
728

729
int
D
Daniel P. Berrange 已提交
730
brSetForwardDelay(const char *brname,
731 732
                  int delay)
{
733 734
    virCommandPtr cmd;
    int ret = -1;
735

736
    cmd = virCommandNew(BRCTL);
D
Daniel P. Berrange 已提交
737
    virCommandAddArgList(cmd, "setfd", brname, NULL);
738
    virCommandAddArgFormat(cmd, "%d", delay);
739

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

743 744 745 746
    ret = 0;
cleanup:
    virCommandFree(cmd);
    return ret;
747 748
}

749 750
/**
 * brSetEnableSTP:
D
Daniel P. Berrange 已提交
751
 * @brname: the bridge name
752 753 754 755 756
 * @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.
 *
757
 * Returns 0 in case of success or -1 on failure
758
 */
759
int
D
Daniel P. Berrange 已提交
760
brSetEnableSTP(const char *brname,
761 762
               int enable)
{
763 764
    virCommandPtr cmd;
    int ret = -1;
765

766
    cmd = virCommandNew(BRCTL);
D
Daniel P. Berrange 已提交
767
    virCommandAddArgList(cmd, "stp", brname,
768 769
                         enable ? "on" : "off",
                         NULL);
770

771 772 773 774 775 776 777
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    ret = 0;
cleanup:
    virCommandFree(cmd);
    return ret;
778 779
}

780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
/**
 * 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.
 */

int
D
Daniel P. Berrange 已提交
796
brCreateTap(char **ifname,
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
            int vnet_hdr ATTRIBUTE_UNUSED,
            int *tapfd)
{
    int fd;
    struct ifreq ifr;

    if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
        return errno;

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

    ifr.ifr_flags = IFF_TAP|IFF_NO_PI;

# ifdef IFF_VNET_HDR
    if (vnet_hdr && brProbeVnetHdr(fd))
        ifr.ifr_flags |= IFF_VNET_HDR;
# endif

    if (virStrcpyStatic(ifr.ifr_name, *ifname) == NULL) {
        errno = EINVAL;
        goto error;
    }

    if (ioctl(fd, TUNSETIFF, &ifr) < 0)
        goto error;

    if (!tapfd &&
        (errno = ioctl(fd, TUNSETPERSIST, 1)))
        goto error;
    VIR_FREE(*ifname);
    if (!(*ifname = strdup(ifr.ifr_name)))
        goto error;
    if(tapfd)
        *tapfd = fd;
    else
        VIR_FORCE_CLOSE(fd);
    return 0;

 error:
    VIR_FORCE_CLOSE(fd);

    return errno;
}

841
#endif /* WITH_BRIDGE */