netdev_vport_profile_conf.c 9.7 KB
Newer Older
1
/*
2
 * Copyright (C) 2009-2012 Red Hat, Inc.
3 4 5 6 7 8 9 10 11 12 13 14
 *
 * 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
15
 * License along with this library.  If not, see
O
Osier Yang 已提交
16
 * <http://www.gnu.org/licenses/>.
17 18 19 20 21 22 23 24 25
 *
 * Authors:
 *     Stefan Berger <stefanb@us.ibm.com>
 *     Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>

#include "netdev_vport_profile_conf.h"
26
#include "virerror.h"
27
#include "viralloc.h"
28 29 30 31 32 33 34

#define VIR_FROM_THIS VIR_FROM_NONE


VIR_ENUM_IMPL(virNetDevVPort, VIR_NETDEV_VPORT_PROFILE_LAST,
              "none",
              "802.1Qbg",
A
Ansis Atteka 已提交
35 36
              "802.1Qbh",
              "openvswitch")
37 38 39


virNetDevVPortProfilePtr
40
virNetDevVPortProfileParse(xmlNodePtr node, unsigned int flags)
41 42 43 44 45 46 47
{
    char *virtPortType;
    char *virtPortManagerID = NULL;
    char *virtPortTypeID = NULL;
    char *virtPortTypeIDVersion = NULL;
    char *virtPortInstanceID = NULL;
    char *virtPortProfileID = NULL;
A
Ansis Atteka 已提交
48
    char *virtPortInterfaceID = NULL;
49 50 51 52 53 54 55 56
    virNetDevVPortProfilePtr virtPort = NULL;
    xmlNodePtr cur = node->children;

    if (VIR_ALLOC(virtPort) < 0) {
        virReportOOMError();
        return NULL;
    }

57 58 59 60
    if ((virtPortType = virXMLPropString(node, "type")) &&
        (virtPort->virtPortType = virNetDevVPortTypeFromString(virtPortType)) <= 0) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("unknown virtualport type %s"), virtPortType);
61 62 63
        goto error;
    }

64 65 66 67
    if ((virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE) &&
        (flags & VIR_VPORT_XML_REQUIRE_TYPE)) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing required virtualport type"));
68 69 70 71 72 73 74 75 76 77
        goto error;
    }

    while (cur != NULL) {
        if (xmlStrEqual(cur->name, BAD_CAST "parameters")) {
            virtPortManagerID = virXMLPropString(cur, "managerid");
            virtPortTypeID = virXMLPropString(cur, "typeid");
            virtPortTypeIDVersion = virXMLPropString(cur, "typeidversion");
            virtPortInstanceID = virXMLPropString(cur, "instanceid");
            virtPortProfileID = virXMLPropString(cur, "profileid");
A
Ansis Atteka 已提交
78
            virtPortInterfaceID = virXMLPropString(cur, "interfaceid");
79 80 81 82 83
            break;
        }
        cur = cur->next;
    }

84 85
    if (virtPortManagerID) {
        unsigned int val;
86

87 88 89 90 91 92 93 94 95 96 97 98 99
        if (virStrToLong_ui(virtPortManagerID, NULL, 0, &val)) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("cannot parse value of managerid parameter"));
            goto error;
        }
        if (val > 0xff) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("value of managerid out of range"));
            goto error;
        }
        virtPort->managerID = (uint8_t)val;
        virtPort->managerID_specified = true;
    }
100

101 102
    if (virtPortTypeID) {
        unsigned int val;
103

104 105 106 107 108 109 110 111 112 113 114 115 116
        if (virStrToLong_ui(virtPortTypeID, NULL, 0, &val)) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("cannot parse value of typeid parameter"));
            goto error;
        }
        if (val > 0xffffff) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("value for typeid out of range"));
            goto error;
        }
        virtPort->typeID = (uint32_t)val;
        virtPort->typeID_specified = true;
    }
117

118 119
    if (virtPortTypeIDVersion) {
        unsigned int val;
120

121 122 123 124 125 126 127 128 129 130 131 132 133
        if (virStrToLong_ui(virtPortTypeIDVersion, NULL, 0, &val)) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("cannot parse value of typeidversion parameter"));
            goto error;
        }
        if (val > 0xff) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("value of typeidversion out of range"));
            goto error;
        }
        virtPort->typeIDVersion = (uint8_t)val;
        virtPort->typeIDVersion_specified = true;
    }
134

135 136 137 138
    if (virtPortInstanceID) {
        if (virUUIDParse(virtPortInstanceID, virtPort->instanceID) < 0) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("cannot parse instanceid parameter as a uuid"));
139 140
            goto error;
        }
141 142 143 144 145 146 147 148 149 150 151 152
        virtPort->instanceID_specified = true;
    }

    if (virtPortProfileID &&
        !virStrcpyStatic(virtPort->profileID, virtPortProfileID)) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("profileid parameter too long"));
        goto error;
    }

    if (virtPortInterfaceID) {
        if (virUUIDParse(virtPortInterfaceID, virtPort->interfaceID) < 0) {
153
            virReportError(VIR_ERR_XML_ERROR, "%s",
154
                           _("cannot parse interfaceid parameter as a uuid"));
155 156
            goto error;
        }
157 158 159 160 161 162 163 164 165 166 167
        virtPort->interfaceID_specified = true;
    }

    /* generate default instanceID/interfaceID if appropriate */
    if (flags & VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS) {
        if (!virtPort->instanceID_specified &&
            (virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
             virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)) {
            if (virUUIDGenerate(virtPort->instanceID) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("cannot generate a random uuid for instanceid"));
A
Ansis Atteka 已提交
168 169
                goto error;
            }
170
            virtPort->instanceID_specified = true;
A
Ansis Atteka 已提交
171
        }
172 173 174 175 176 177
        if (!virtPort->interfaceID_specified &&
            (virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
             virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)) {
            if (virUUIDGenerate(virtPort->interfaceID) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("cannot generate a random uuid for interfaceid"));
A
Ansis Atteka 已提交
178 179
                goto error;
            }
180
            virtPort->interfaceID_specified = true;
A
Ansis Atteka 已提交
181
        }
182
    }
183

184 185 186 187
    /* check for required/unsupported attributes */

    if ((flags & VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES) &&
        (virNetDevVPortProfileCheckComplete(virtPort, false) < 0)) {
188 189 190
        goto error;
    }

191 192 193
    if (virNetDevVPortProfileCheckNoExtras(virtPort) < 0)
        goto error;

194 195 196 197 198 199 200
cleanup:
    VIR_FREE(virtPortManagerID);
    VIR_FREE(virtPortTypeID);
    VIR_FREE(virtPortTypeIDVersion);
    VIR_FREE(virtPortInstanceID);
    VIR_FREE(virtPortProfileID);
    VIR_FREE(virtPortType);
201
    VIR_FREE(virtPortInterfaceID);
202 203 204 205 206 207 208 209 210 211 212 213 214

    return virtPort;

error:
    VIR_FREE(virtPort);
    goto cleanup;
}


int
virNetDevVPortProfileFormat(virNetDevVPortProfilePtr virtPort,
                            virBufferPtr buf)
{
215 216
    enum virNetDevVPortProfile type;
    bool noParameters;
217

218
    if (!virtPort)
219 220
        return 0;

221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
    noParameters = !(virtPort->managerID_specified ||
                     virtPort->typeID_specified ||
                     virtPort->typeIDVersion_specified ||
                     virtPort->instanceID_specified ||
                     virtPort->profileID[0] ||
                     virtPort->interfaceID_specified);

    type = virtPort->virtPortType;
    if (type == VIR_NETDEV_VPORT_PROFILE_NONE) {
        if (noParameters)
            return 0;
        virBufferAddLit(buf, "<virtualport>\n");
    } else {
        if (noParameters) {
            virBufferAsprintf(buf, "<virtualport type='%s'/>\n",
                              virNetDevVPortTypeToString(type));
            return 0;
A
Ansis Atteka 已提交
238
        } else {
239 240
            virBufferAsprintf(buf, "<virtualport type='%s'>\n",
                              virNetDevVPortTypeToString(type));
A
Ansis Atteka 已提交
241
        }
242 243
    }
    virBufferAddLit(buf, "  <parameters");
A
Ansis Atteka 已提交
244

245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
    if (virtPort->managerID_specified &&
        (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        virBufferAsprintf(buf, " managerid='%d'", virtPort->managerID);
    }
    if (virtPort->typeID_specified &&
        (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        virBufferAsprintf(buf, " typeid='%d'", virtPort->typeID);
    }
    if (virtPort->typeIDVersion_specified &&
        (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        virBufferAsprintf(buf, " typeidversion='%d'",
                          virtPort->typeIDVersion);
    }
    if (virtPort->instanceID_specified &&
        (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
A
Ansis Atteka 已提交
265

266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
        virUUIDFormat(virtPort->instanceID, uuidstr);
        virBufferAsprintf(buf, " instanceid='%s'", uuidstr);
    }
    if (virtPort->interfaceID_specified &&
        (type == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(virtPort->interfaceID, uuidstr);
        virBufferAsprintf(buf, " interfaceid='%s'", uuidstr);
    }
    if (virtPort->profileID[0] &&
        (type == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
         type == VIR_NETDEV_VPORT_PROFILE_8021QBH ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        virBufferAsprintf(buf, " profileid='%s'", virtPort->profileID);
282 283
    }

284
    virBufferAddLit(buf, "/>\n");
285 286 287
    virBufferAddLit(buf, "</virtualport>\n");
    return 0;
}