virinterfaceobj.c 11.1 KB
Newer Older
J
John Ferlan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * virinterfaceobj.c: interface object handling
 *                    (derived from interface_conf.c)
 *
 * 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, see
 * <http://www.gnu.org/licenses/>.
 */

#include <config.h>

#include "datatypes.h"
#include "interface_conf.h"

#include "viralloc.h"
#include "virerror.h"
#include "virinterfaceobj.h"
28
#include "virhash.h"
J
John Ferlan 已提交
29 30 31 32 33 34 35
#include "virlog.h"
#include "virstring.h"

#define VIR_FROM_THIS VIR_FROM_INTERFACE

VIR_LOG_INIT("conf.virinterfaceobj");

36
struct _virInterfaceObj {
37
    virObjectLockable parent;
38 39 40 41

    bool active;           /* true if interface is active (up) */
    virInterfaceDefPtr def; /* The interface definition */
};
J
John Ferlan 已提交
42

43
struct _virInterfaceObjList {
44 45
    virObjectRWLockable parent;

46 47 48
    /* name string -> virInterfaceObj  mapping
     * for O(1), lockless lookup-by-name */
    virHashTable *objsName;
49
};
J
John Ferlan 已提交
50 51 52

/* virInterfaceObj manipulation */

53
static virClassPtr virInterfaceObjClass;
54
static virClassPtr virInterfaceObjListClass;
55
static void virInterfaceObjDispose(void *obj);
56
static void virInterfaceObjListDispose(void *obj);
57 58 59 60 61 62 63 64 65 66

static int
virInterfaceObjOnceInit(void)
{
    if (!(virInterfaceObjClass = virClassNew(virClassForObjectLockable(),
                                             "virInterfaceObj",
                                             sizeof(virInterfaceObj),
                                             virInterfaceObjDispose)))
        return -1;

67 68 69 70 71 72
    if (!(virInterfaceObjListClass = virClassNew(virClassForObjectRWLockable(),
                                                 "virInterfaceObjList",
                                                 sizeof(virInterfaceObjList),
                                                 virInterfaceObjListDispose)))
        return -1;

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
    return 0;
}

VIR_ONCE_GLOBAL_INIT(virInterfaceObj)


static void
virInterfaceObjDispose(void *opaque)
{
    virInterfaceObjPtr obj = opaque;

    virInterfaceDefFree(obj->def);
}


88
static virInterfaceObjPtr
89
virInterfaceObjNew(void)
90 91 92
{
    virInterfaceObjPtr obj;

93
    if (virInterfaceObjInitialize() < 0)
94 95
        return NULL;

96
    if (!(obj = virObjectLockableNew(virInterfaceObjClass)))
97 98
        return NULL;

99
    virObjectLock(obj);
100 101 102 103 104

    return obj;
}


105
void
106
virInterfaceObjEndAPI(virInterfaceObjPtr *obj)
J
John Ferlan 已提交
107
{
108
    if (!*obj)
J
John Ferlan 已提交
109 110
        return;

111 112 113
    virObjectUnlock(*obj);
    virObjectUnref(*obj);
    *obj = NULL;
J
John Ferlan 已提交
114 115 116
}


117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
virInterfaceDefPtr
virInterfaceObjGetDef(virInterfaceObjPtr obj)
{
    return obj->def;
}


bool
virInterfaceObjIsActive(virInterfaceObjPtr obj)
{
    return obj->active;
}


void
virInterfaceObjSetActive(virInterfaceObjPtr obj,
                         bool active)
{
    obj->active = active;
}


139
/* virInterfaceObjList manipulation */
140 141 142 143 144
virInterfaceObjListPtr
virInterfaceObjListNew(void)
{
    virInterfaceObjListPtr interfaces;

145 146 147 148
    if (virInterfaceObjInitialize() < 0)
        return NULL;

    if (!(interfaces = virObjectRWLockableNew(virInterfaceObjListClass)))
149
        return NULL;
150

151 152 153 154 155
    if (!(interfaces->objsName = virHashCreate(10, virObjectFreeHashData))) {
        virObjectUnref(interfaces);
        return NULL;
    }

156 157 158 159
    return interfaces;
}


160 161 162
struct _virInterfaceObjFindMACData {
    const char *matchStr;
    bool error;
163 164 165
    int nnames;
    int maxnames;
    char **const names;
166 167 168 169 170 171 172 173 174 175 176 177 178
};

static int
virInterfaceObjListFindByMACStringCb(void *payload,
                                     const void *name ATTRIBUTE_UNUSED,
                                     void *opaque)
{
    virInterfaceObjPtr obj = payload;
    struct _virInterfaceObjFindMACData *data = opaque;

    if (data->error)
        return 0;

179
    if (data->nnames == data->maxnames)
180 181 182 183 184
        return 0;

    virObjectLock(obj);

    if (STRCASEEQ(obj->def->mac, data->matchStr)) {
185
        if (VIR_STRDUP(data->names[data->nnames], obj->def->name) < 0) {
186 187 188
            data->error = true;
            goto cleanup;
        }
189
        data->nnames++;
190 191 192 193 194 195 196 197
    }

 cleanup:
    virObjectUnlock(obj);
    return 0;
}


198
int
199 200
virInterfaceObjListFindByMACString(virInterfaceObjListPtr interfaces,
                                   const char *mac,
201
                                   char **const matches,
202
                                   int maxmatches)
J
John Ferlan 已提交
203
{
204 205
    struct _virInterfaceObjFindMACData data = { .matchStr = mac,
                                                .error = false,
206 207 208
                                                .nnames = 0,
                                                .maxnames = maxmatches,
                                                .names = matches };
J
John Ferlan 已提交
209

210
    virObjectRWLockRead(interfaces);
211 212
    virHashForEach(interfaces->objsName, virInterfaceObjListFindByMACStringCb,
                   &data);
213
    virObjectRWUnlock(interfaces);
214 215 216 217

    if (data.error)
        goto error;

218
    return data.nnames;
219 220

 error:
221 222
    while (--data.nnames >= 0)
        VIR_FREE(data.names[data.nnames]);
223 224

    return -1;
J
John Ferlan 已提交
225 226
}

227

228 229 230 231 232 233 234 235
static virInterfaceObjPtr
virInterfaceObjListFindByNameLocked(virInterfaceObjListPtr interfaces,
                                    const char *name)
{
    return virObjectRef(virHashLookup(interfaces->objsName, name));
}


236
virInterfaceObjPtr
237 238
virInterfaceObjListFindByName(virInterfaceObjListPtr interfaces,
                              const char *name)
J
John Ferlan 已提交
239
{
240
    virInterfaceObjPtr obj;
241
    virObjectRWLockRead(interfaces);
242
    obj = virInterfaceObjListFindByNameLocked(interfaces, name);
243
    virObjectRWUnlock(interfaces);
244 245
    if (obj)
        virObjectLock(obj);
J
John Ferlan 已提交
246

247
    return obj;
J
John Ferlan 已提交
248 249
}

250 251

void
252
virInterfaceObjListDispose(void *obj)
J
John Ferlan 已提交
253
{
254
    virInterfaceObjListPtr interfaces = obj;
J
John Ferlan 已提交
255

256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
    virHashFree(interfaces->objsName);
}


struct _virInterfaceObjListCloneData {
    bool error;
    virInterfaceObjListPtr dest;
};

static int
virInterfaceObjListCloneCb(void *payload,
                           const void *name ATTRIBUTE_UNUSED,
                           void *opaque)
{
    virInterfaceObjPtr srcObj = payload;
    struct _virInterfaceObjListCloneData *data = opaque;
    char *xml = NULL;
    virInterfaceDefPtr backup = NULL;
    virInterfaceObjPtr obj;

    if (data->error)
        return 0;

    virObjectLock(srcObj);

    if (!(xml = virInterfaceDefFormat(srcObj->def)))
        goto error;

    if (!(backup = virInterfaceDefParseString(xml)))
        goto error;
    VIR_FREE(xml);

    if (!(obj = virInterfaceObjListAssignDef(data->dest, backup)))
        goto error;
    virInterfaceObjEndAPI(&obj);

    virObjectUnlock(srcObj);
    return 0;

 error:
    data->error = true;
    VIR_FREE(xml);
    virInterfaceDefFree(backup);
    virObjectUnlock(srcObj);
    return 0;
J
John Ferlan 已提交
301 302
}

303

304 305
virInterfaceObjListPtr
virInterfaceObjListClone(virInterfaceObjListPtr interfaces)
J
John Ferlan 已提交
306
{
307 308
    struct _virInterfaceObjListCloneData data = { .error = false,
                                                  .dest = NULL };
J
John Ferlan 已提交
309

310 311
    if (!interfaces)
        return NULL;
J
John Ferlan 已提交
312

313
    if (!(data.dest = virInterfaceObjListNew()))
314 315
        return NULL;

316
    virObjectRWLockRead(interfaces);
317
    virHashForEach(interfaces->objsName, virInterfaceObjListCloneCb, &data);
318
    virObjectRWUnlock(interfaces);
J
John Ferlan 已提交
319

320 321 322 323
    if (data.error)
        goto error;

    return data.dest;
324 325

 error:
326
    virObjectUnref(data.dest);
327
    return NULL;
J
John Ferlan 已提交
328 329
}

330 331

virInterfaceObjPtr
332 333
virInterfaceObjListAssignDef(virInterfaceObjListPtr interfaces,
                             virInterfaceDefPtr def)
J
John Ferlan 已提交
334
{
335
    virInterfaceObjPtr obj;
J
John Ferlan 已提交
336

337 338
    virObjectRWLockWrite(interfaces);
    if ((obj = virInterfaceObjListFindByNameLocked(interfaces, def->name))) {
339
        virInterfaceDefFree(obj->def);
340 341 342
    } else {
        if (!(obj = virInterfaceObjNew()))
            goto error;
J
John Ferlan 已提交
343

344 345 346
        if (virHashAddEntry(interfaces->objsName, def->name, obj) < 0)
            goto error;
        virObjectRef(obj);
J
John Ferlan 已提交
347 348
    }

349
    obj->def = def;
350
    virObjectRWUnlock(interfaces);
351 352 353 354 355 356 357

    return obj;

 error:
    virInterfaceObjEndAPI(&obj);
    virObjectRWUnlock(interfaces);
    return NULL;
J
John Ferlan 已提交
358 359
}

360 361

void
362 363
virInterfaceObjListRemove(virInterfaceObjListPtr interfaces,
                          virInterfaceObjPtr obj)
J
John Ferlan 已提交
364
{
365 366
    if (!obj)
        return;
J
John Ferlan 已提交
367

368
    virObjectRef(obj);
369
    virObjectUnlock(obj);
370
    virObjectRWLockWrite(interfaces);
371 372 373 374
    virObjectLock(obj);
    virHashRemoveEntry(interfaces->objsName, obj->def->name);
    virObjectUnlock(obj);
    virObjectUnref(obj);
375
    virObjectRWUnlock(interfaces);
J
John Ferlan 已提交
376
}
377 378


379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
struct _virInterfaceObjNumOfInterfacesData {
    bool wantActive;
    int count;
};

static int
virInterfaceObjListNumOfInterfacesCb(void *payload,
                                     const void *name ATTRIBUTE_UNUSED,
                                     void *opaque)
{
    virInterfaceObjPtr obj = payload;
    struct _virInterfaceObjNumOfInterfacesData *data = opaque;

    virObjectLock(obj);

    if (data->wantActive == virInterfaceObjIsActive(obj))
        data->count++;

    virObjectUnlock(obj);
    return 0;
}


402
int
403 404
virInterfaceObjListNumOfInterfaces(virInterfaceObjListPtr interfaces,
                                   bool wantActive)
405
{
406 407
    struct _virInterfaceObjNumOfInterfacesData data = {
        .wantActive = wantActive, .count = 0 };
408

409
    virObjectRWLockRead(interfaces);
410 411
    virHashForEach(interfaces->objsName, virInterfaceObjListNumOfInterfacesCb,
                   &data);
412
    virObjectRWUnlock(interfaces);
413

414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
    return data.count;
}


struct _virInterfaceObjGetNamesData {
    bool wantActive;
    bool error;
    int nnames;
    int maxnames;
    char **const names;
};

static int
virInterfaceObjListGetNamesCb(void *payload,
                              const void *name ATTRIBUTE_UNUSED,
                              void *opaque)
{
    virInterfaceObjPtr obj = payload;
    struct _virInterfaceObjGetNamesData *data = opaque;

    if (data->error)
        return 0;

    if (data->maxnames >= 0 && data->nnames == data->maxnames)
        return 0;

    virObjectLock(obj);

    if (data->wantActive != virInterfaceObjIsActive(obj))
        goto cleanup;

    if (VIR_STRDUP(data->names[data->nnames], obj->def->name) < 0) {
        data->error = true;
        goto cleanup;
    }

    data->nnames++;

 cleanup:
    virObjectUnlock(obj);
    return 0;
455
}
456 457 458


int
459 460 461 462
virInterfaceObjListGetNames(virInterfaceObjListPtr interfaces,
                            bool wantActive,
                            char **const names,
                            int maxnames)
463
{
464 465 466
    struct _virInterfaceObjGetNamesData data = {
        .wantActive = wantActive, .error = false, .nnames = 0,
        .maxnames = maxnames,  .names = names };
467

468
    virObjectRWLockRead(interfaces);
469
    virHashForEach(interfaces->objsName, virInterfaceObjListGetNamesCb, &data);
470
    virObjectRWUnlock(interfaces);
471

472 473
    if (data.error)
        goto error;
474

475 476 477 478 479
    return data.nnames;

 error:
    while (--data.nnames >= 0)
        VIR_FREE(data.names[data.nnames]);
480 481 482

    return -1;
}