virnetdevopenvswitch.c 5.9 KB
Newer Older
A
Ansis Atteka 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Copyright (C) 2012 Nicira, Inc.
 *
 * 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
O
Osier Yang 已提交
15 16
 * License along with this library;  If not, see
 * <http://www.gnu.org/licenses/>.
A
Ansis Atteka 已提交
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 *
 * Authors:
 *     Dan Wendlandt <dan@nicira.com>
 *     Kyle Mestery <kmestery@cisco.com>
 *     Ansis Atteka <aatteka@nicira.com>
 */

#include <config.h>

#include "virnetdevopenvswitch.h"
#include "command.h"
#include "memory.h"
#include "virterror_internal.h"
#include "virmacaddr.h"

#define VIR_FROM_THIS VIR_FROM_NONE

/**
 * virNetDevOpenvswitchAddPort:
 * @brname: the bridge name
 * @ifname: the network interface name
 * @macaddr: the mac address of the virtual interface
39
 * @vmuuid: the Domain UUID that has this interface
A
Ansis Atteka 已提交
40 41 42 43 44 45 46
 * @ovsport: the ovs specific fields
 *
 * Add an interface to the OVS bridge
 *
 * Returns 0 in case of success or -1 in case of failure.
 */
int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
47
                                   const virMacAddrPtr macaddr,
48
                                   const unsigned char *vmuuid,
49 50
                                   virNetDevVPortProfilePtr ovsport,
                                   virNetDevVlanPtr virtVlan)
A
Ansis Atteka 已提交
51 52
{
    int ret = -1;
53
    int i = 0;
A
Ansis Atteka 已提交
54 55
    virCommandPtr cmd = NULL;
    char macaddrstr[VIR_MAC_STRING_BUFLEN];
56 57
    char ifuuidstr[VIR_UUID_STRING_BUFLEN];
    char vmuuidstr[VIR_UUID_STRING_BUFLEN];
A
Ansis Atteka 已提交
58 59 60
    char *attachedmac_ex_id = NULL;
    char *ifaceid_ex_id = NULL;
    char *profile_ex_id = NULL;
61
    char *vmid_ex_id = NULL;
62
    virBuffer buf = VIR_BUFFER_INITIALIZER;
A
Ansis Atteka 已提交
63 64

    virMacAddrFormat(macaddr, macaddrstr);
65
    virUUIDFormat(ovsport->interfaceID, ifuuidstr);
66
    virUUIDFormat(vmuuid, vmuuidstr);
A
Ansis Atteka 已提交
67 68 69

    if (virAsprintf(&attachedmac_ex_id, "external-ids:attached-mac=\"%s\"",
                    macaddrstr) < 0)
70
        goto out_of_memory;
A
Ansis Atteka 已提交
71
    if (virAsprintf(&ifaceid_ex_id, "external-ids:iface-id=\"%s\"",
72
                    ifuuidstr) < 0)
73
        goto out_of_memory;
74 75
    if (virAsprintf(&vmid_ex_id, "external-ids:vm-id=\"%s\"",
                    vmuuidstr) < 0)
76
        goto out_of_memory;
77
    if (ovsport->profileID[0] != '\0') {
A
Ansis Atteka 已提交
78
        if (virAsprintf(&profile_ex_id, "external-ids:port-profile=\"%s\"",
79
                        ovsport->profileID) < 0)
80
            goto out_of_memory;
A
Ansis Atteka 已提交
81
    }
82 83

    if (virtVlan && virtVlan->nTags > 0) {
84 85

        /* Trunk port first */
86
        if (virtVlan->trunk) {
87
            virBufferAddLit(&buf, "trunk=");
88 89 90 91 92 93 94

            /*
             * Trunk ports have at least one VLAN. Do the first one
             * outside the "for" loop so we can put a "," at the
             * start of the for loop if there are more than one VLANs
             * on this trunk port.
             */
95
            virBufferAsprintf(&buf, "%d", virtVlan->tag[i]);
96 97

            for (i = 1; i < virtVlan->nTags; i++) {
98 99
                virBufferAddLit(&buf, ",");
                virBufferAsprintf(&buf, "%d", virtVlan->tag[i]);
100
            }
101
        } else if (virtVlan->nTags) {
102
            virBufferAsprintf(&buf, "tag=%d", virtVlan->tag[0]);
103 104
        }
    }
A
Ansis Atteka 已提交
105 106

    cmd = virCommandNew(OVSVSCTL);
107

108
    virCommandAddArgList(cmd, "--timeout=5", "--", "--may-exist", "add-port",
109 110 111 112 113
                        brname, ifname, NULL);

    if (virBufferUse(&buf) != 0)
        virCommandAddArgList(cmd, virBufferCurrentContent(&buf), NULL);

114
    if (ovsport->profileID[0] == '\0') {
115
        virCommandAddArgList(cmd,
A
Ansis Atteka 已提交
116 117
                        "--", "set", "Interface", ifname, attachedmac_ex_id,
                        "--", "set", "Interface", ifname, ifaceid_ex_id,
118
                        "--", "set", "Interface", ifname, vmid_ex_id,
A
Ansis Atteka 已提交
119 120 121 122
                        "--", "set", "Interface", ifname,
                        "external-ids:iface-status=active",
                        NULL);
    } else {
123
        virCommandAddArgList(cmd,
A
Ansis Atteka 已提交
124 125
                        "--", "set", "Interface", ifname, attachedmac_ex_id,
                        "--", "set", "Interface", ifname, ifaceid_ex_id,
126
                        "--", "set", "Interface", ifname, vmid_ex_id,
A
Ansis Atteka 已提交
127 128 129 130 131 132 133 134 135 136 137 138 139
                        "--", "set", "Interface", ifname, profile_ex_id,
                        "--", "set", "Interface", ifname,
                        "external-ids:iface-status=active",
                        NULL);
    }

    if (virCommandRun(cmd, NULL) < 0) {
        virReportSystemError(VIR_ERR_INTERNAL_ERROR,
                             _("Unable to add port %s to OVS bridge %s"),
                             ifname, brname);
        goto cleanup;
    }

140 141
    ret = 0;
cleanup:
142
    virBufferFreeAndReset(&buf);
143 144
    VIR_FREE(attachedmac_ex_id);
    VIR_FREE(ifaceid_ex_id);
145
    VIR_FREE(vmid_ex_id);
146 147 148
    VIR_FREE(profile_ex_id);
    virCommandFree(cmd);
    return ret;
149 150 151 152

out_of_memory:
    virReportOOMError();
    goto cleanup;
A
Ansis Atteka 已提交
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
}

/**
 * virNetDevOpenvswitchRemovePort:
 * @ifname: the network interface name
 *
 * Deletes an interface from a OVS bridge
 *
 * Returns 0 in case of success or -1 in case of failure.
 */
int virNetDevOpenvswitchRemovePort(const char *brname ATTRIBUTE_UNUSED, const char *ifname)
{
    int ret = -1;
    virCommandPtr cmd = NULL;

    cmd = virCommandNew(OVSVSCTL);
169
    virCommandAddArgList(cmd, "--timeout=5", "--", "--if-exists", "del-port", ifname, NULL);
A
Ansis Atteka 已提交
170 171 172 173 174 175 176 177 178 179 180 181

    if (virCommandRun(cmd, NULL) < 0) {
        virReportSystemError(VIR_ERR_INTERNAL_ERROR,
                             _("Unable to delete port %s from OVS"), ifname);
        goto cleanup;
    }
    ret = 0;

    cleanup:
        virCommandFree(cmd);
        return ret;
}