[Libvirt-cim] [V4 PATCH 6/8] vlan library - add help functions and error defines

Wenchao Xia xiawenc at linux.vnet.ibm.com
Wed Jan 18 09:42:44 UTC 2012


    This patch have help functions for libnetwork. It contains macro defines
and help functions for host network configuration. It also provide some basic
function such as conditional merge char*, int and properties of structure
EthIface.

Signed-off-by: Wenchao Xia <xiawenc at cn.ibm.com>
---
 libnetwork/dll_magic.h           |   13 ++
 libnetwork/host_network_error.h  |   23 ++++
 libnetwork/host_network_helper.c |  266 ++++++++++++++++++++++++++++++++++++++
 libnetwork/host_network_helper.h |  177 +++++++++++++++++++++++++
 4 files changed, 479 insertions(+), 0 deletions(-)
 create mode 100644 libnetwork/dll_magic.h
 create mode 100644 libnetwork/host_network_error.h
 create mode 100644 libnetwork/host_network_helper.c
 create mode 100644 libnetwork/host_network_helper.h

diff --git a/libnetwork/dll_magic.h b/libnetwork/dll_magic.h
new file mode 100644
index 0000000..36bca83
--- /dev/null
+++ b/libnetwork/dll_magic.h
@@ -0,0 +1,13 @@
+#ifndef DLL_MAGIC_H
+#define DLL_MAGIC_H
+
+
+#if __GNUC__ >= 4
+    #ifdef DLL_BUILD
+        #define DLL_PUBLIC __attribute__ ((visibility ("default")))
+    #else
+        #define DLL_PUBLIC
+    #endif
+#endif
+
+#endif
diff --git a/libnetwork/host_network_error.h b/libnetwork/host_network_error.h
new file mode 100644
index 0000000..1882172
--- /dev/null
+++ b/libnetwork/host_network_error.h
@@ -0,0 +1,23 @@
+#ifndef HOST_NETWORK_ERROR_H
+#define HOST_NETWORK_ERROR_H
+
+#define ERR_REQUEST_NOT_SUPPORT -1
+
+#define ERR_LIBNETLINK -80
+#define ERR_LIBBR -90
+
+#define ERR_DEVICE_EXCEED_MAXNUM -100
+#define ERR_DEVICE_EXIST -101
+#define ERR_DEVICE_NOT_EXIST -102
+#define ERR_DEVICE_ALREADY_DONE -103
+#define ERR_DEVICE_CONNECT_OTHER -104
+
+#define ERR_FILE_OP_FAIL -125
+#define ERR_FILE_EMPTY  -126
+#define ERR_FILE_TOO_LARGE -127
+#define ERR_FILE_CONT_TOO_LARGE -128
+#define ERR_FILE_LOCK_FAIL -129
+
+#define ERR_PERSIST_NOT_REDHAT -200
+
+#endif
diff --git a/libnetwork/host_network_helper.c b/libnetwork/host_network_helper.c
new file mode 100644
index 0000000..cda2732
--- /dev/null
+++ b/libnetwork/host_network_helper.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * Authors:
+ *  Wenchao Xia <xiawenc at cn.ibm.com>
+ *
+ * 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.
+ */
+
+
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+
+#include "host_network_helper.h"
+#include "host_network_error.h"
+
+static int compare_qos_8021q(const void *p1, const void *p2)
+{
+    const VLAN_Qos_8021q_elem *qos1 = (VLAN_Qos_8021q_elem *)p1;
+    const VLAN_Qos_8021q_elem *qos2 = (VLAN_Qos_8021q_elem *)p2;
+    int ret = 0;
+    if ((qos1->from) > (qos2->from)) {
+        ret = 1;
+    }
+    return ret;
+}
+
+/* it need to be checked see whether these are the conditions */
+int vlan_8021q_qos_check_valid(VLAN_Qos_8021q *pqos)
+{
+    int ret = 1;
+    int i = 0;
+    int last_num = -1;
+    if ((pqos->count < 0) || (pqos->count > 8)) {
+        ret = 0;
+        goto out;
+    } else if (pqos->count == 0) {
+        goto out;
+    }
+    qsort((void *)pqos->values, pqos->count, sizeof(VLAN_Qos_8021q_elem),
+                            compare_qos_8021q);
+
+    while (i < pqos->count) {
+        if (pqos->values[i].from == last_num) {
+            CU_DEBUG("error: vlan 802.1.q qos setting have same <from> values: "
+                     "last is %d, new is %d", last_num, pqos->values[i].from);
+            ret = 0;
+            goto out;
+        }
+        last_num = pqos->values[i].from;
+        if ((pqos->values[i].from < 0) || (pqos->values[i].from >= 8)) {
+            CU_DEBUG("error: vlan 802.1.q qos setting have outbound value: "
+                     "from is %d.", pqos->values[i].from);
+            ret = 0;
+            goto out;
+        }
+        if ((pqos->values[i].to < 0) || (pqos->values[i].to >= 8)) {
+            CU_DEBUG("error: vlan 802.1.q qos setting have outbound value: "
+                     "to is %d.", pqos->values[i].to);
+            ret = 0;
+            goto out;
+        }
+        i++;
+    }
+
+ out:
+    return ret;
+}
+
+int vlan_8021q_qos_str_to_num(VLAN_Qos_8021q *pqos, const char* str)
+{
+    int ret = 1;
+    char *str_line = NULL;
+    char *temp;
+    char *saveptr = NULL;
+    char *invalptr1, *invalptr2;
+    int qos_num1, qos_num2;
+    VLAN_Qos_8021q qos;
+
+    if (str == NULL) {
+        ret = 0;
+        goto out;
+    }
+    if (str[0] == '\0') {
+        ret = 1;
+        pqos->count = 0;
+        CU_DEBUG("empty vlan 802.1.q qos string found.");
+        goto out;
+    }
+    str_line = SAFE_STRDUP(str);
+    qos.count = 0;
+
+    temp = strtok_r(str_line, " ", &saveptr);
+    while (temp != NULL) {
+        qos_num1 = strtol(temp, &invalptr1, 10);
+        if (temp == invalptr1) {
+            ret = 0;
+            goto out;
+        }
+        if (*invalptr1 != ':') {
+            ret = 0;
+            goto out;
+        }
+        invalptr1++;
+        qos_num2 = strtol(invalptr1, &invalptr2, 10);
+        if (invalptr1 == invalptr2) {
+            ret = 0;
+            goto out;
+        }
+        if (*invalptr2 != '\0') {
+            ret = 0;
+            goto out;
+        }
+        if (qos.count >= 8) {
+            ret = 0;
+            CU_DEBUG("too many settings found in vlan 802.1.q qos string [%s]",
+                        str);
+            goto out;
+        }
+        qos.values[qos.count].from = qos_num1;
+        qos.values[qos.count].to = qos_num2;
+        qos.count++;
+        temp = strtok_r(NULL, " ", &saveptr);
+    }
+    ret = vlan_8021q_qos_check_valid(&qos);
+    if (ret == 1) {
+        *pqos = qos;
+    }
+
+ out:
+    if (ret != 1) {
+        CU_DEBUG("vlan 802.1.q qos string [%s] is invalid.", str);
+    }
+    SAFE_FREE(str_line);
+    return ret;
+}
+
+int vlan_8021q_qos_num_to_str(char **str, const VLAN_Qos_8021q *pqos)
+{
+    char temp[16];
+    int i;
+    VLAN_Qos_8021q qos = *pqos;
+    int ret = vlan_8021q_qos_check_valid(&qos);
+    if (ret != 1) {
+        goto out;
+    }
+    SAFE_MALLOC(*str, 64);
+    *str[0] = '\0';
+    if (qos.count == 0) {
+        goto out;
+    }
+    i = 0;
+    snprintf(temp, sizeof(temp), "%d:%d",
+            qos.values[i].from, qos.values[i].to);
+    strcat(*str, temp);
+    i++;
+    while (i < qos.count) {
+        strcat(*str, " ");
+        snprintf(temp, sizeof(temp), "%d:%d",
+                qos.values[i].from, qos.values[i].to);
+        strcat(*str, temp);
+        i++;
+    }
+
+ out:
+    return ret;
+}
+
+char *combine_file_name(const char *prefix, const char *name)
+{
+    char *ret = NULL;
+    int size;
+    size = strlen(prefix) + strlen(name) + 1;
+    SAFE_CALLOC(ret, size, sizeof(char));
+    snprintf(ret, size, "%s%s", prefix, name);
+    return ret;
+}
+
+char *translate_error_no(int errno)
+{
+    char *ret = NULL;
+    switch (errno) {
+    case ERR_REQUEST_NOT_SUPPORT:
+        ret = "request is not supported now";
+        break;
+
+    case ERR_LIBNETLINK:
+        ret = "error happend in netlink.";
+        break;
+    case ERR_LIBBR:
+        ret = "error happend in bridge commands.";
+        break;
+
+    case ERR_DEVICE_EXCEED_MAXNUM:
+        ret = "too many devices found or set, check the environment.";
+        break;
+    case ERR_DEVICE_EXIST:
+        ret = "device already exist, can not execute the command.";
+        break;
+    case ERR_DEVICE_NOT_EXIST:
+        ret = "device do not exist, can not execute the command.";
+        break;
+    case ERR_DEVICE_ALREADY_DONE:
+        ret = "the operation you want have been done before, "
+                "will not do it again.";
+        break;
+    case ERR_DEVICE_CONNECT_OTHER:
+        ret = "the device you want to connect have been connect to another"
+              " device, can't change it directly.";
+        break;
+
+    case ERR_FILE_OP_FAIL:
+        ret = "failed in accessing the file.";
+        break;
+    case ERR_FILE_EMPTY:
+        ret = "the file it want is empty.";
+        break;
+    case ERR_FILE_TOO_LARGE:
+        ret = "the file it want is too large.";
+        break;
+    case ERR_FILE_CONT_TOO_LARGE:
+        ret = "the content it want to combine to file is too large.";
+        break;
+    case ERR_FILE_LOCK_FAIL:
+        ret = "failed in locking the file, "
+                    "check if other process is using it.";
+        break;
+
+    case ERR_PERSIST_NOT_REDHAT:
+        ret = "host is not a RedHat distribution, can't persist the "
+             "configuration, it would not take effect after host is "
+             "rebooted. Other version would be supported in the future. "
+             "If you are sure host is RedHat, make sure command "
+             "<lsb_release -a> could work.";
+        break;
+
+    default:
+        ret = "internal error.";
+        break;
+    }
+    return ret;
+}
+
+int get_simple_state(struct EthIface *piface)
+{
+    if ((piface->eth_type & ETH_TYPE_ETHER_ANY) &&
+        (piface->eth_type & ETH_TYPE_ETHER_SUB_BRIDGE)) {
+        if (piface->run_prop.status == IF_OPER_UNKNOWN) {
+            return 1;
+        }
+    }
+    if (piface->run_prop.status == IF_OPER_UP) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
diff --git a/libnetwork/host_network_helper.h b/libnetwork/host_network_helper.h
new file mode 100644
index 0000000..fea4f05
--- /dev/null
+++ b/libnetwork/host_network_helper.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * Authors:
+ *  Wenchao Xia <xiawenc at cn.ibm.com>
+ *
+ * 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.
+ */
+
+
+#ifndef HOST_NETWORK_HELPER_H
+#define HOST_NETWORK_HELPER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+#include "dll_magic.h"
+#include "host_network_basic.h"
+
+#ifdef TESTLIB
+#include "TestDefines.h"
+#else
+#include <libcmpiutil/libcmpiutil.h>
+#endif
+
+#define CMD_DEBUG_LEVEL 2
+
+/* macro functions */
+#define CMD_DEBUG(lvl, fmt, args...) do { \
+    if (CMD_DEBUG_LEVEL && (lvl) <= CMD_DEBUG_LEVEL) { \
+        debug_print(fmt, ##args); \
+    } \
+} while (0)
+
+#define SAFE_MALLOC(p, size) \
+{ \
+    (p) = malloc((size)); \
+    if ((p) == NULL) { \
+        CU_DEBUG("malloc failed."); \
+    } \
+}
+
+#define SAFE_CALLOC(p, nmen, size) \
+{ \
+    (p) = calloc((nmen), (size)); \
+    if ((p) == NULL) { \
+        CU_DEBUG("calloc failed."); \
+    } \
+}
+
+#define SAFE_FREE(p) {free(p); (p) = NULL; }
+
+
+/* Macro used to compare two char*, it would skip if ref is NULL. It would
+   only set the result when src != ref, user need to set the result to 1 by
+   default before use the macro. If not set, the it could be used to do
+   check multi times in "one fail all die" mode. Empty lines is the place
+   where result should be set to 1. */
+#define CHARS_COMPARE_BY_REF(src, ref, result) do { \
+    if ((ref) == NULL) { \
+        ; \
+    } else { \
+        if ((src) == NULL) { \
+            (result) = 0; \
+        } else { \
+            if (0 == strcmp((src), (ref))) { \
+                ; \
+            } else { \
+                (result) = 0; \
+            } \
+        } \
+    } \
+} while (0)
+
+/* ignore case version */
+#define CHARS_COMPARE_CASE_BY_REF(src, ref, result) do { \
+    if ((ref) == NULL) { \
+        ; \
+    } else { \
+        if ((src) == NULL) { \
+            (result) = 0; \
+        } else { \
+            if (0 == strcasecmp((src), (ref))) { \
+                ; \
+            } else { \
+                (result) = 0; \
+            } \
+        } \
+    } \
+} while (0)
+
+/* compare the value if ref != default */
+#define NUM_COMPARE_BY_REF(src, ref, result, default) do { \
+    if ((ref) == (default)) { \
+        ; \
+    } else { \
+        if ((src) == (ref)) { \
+            ; \
+        } else { \
+            result = 0; \
+        } \
+    } \
+} while (0)
+
+/* merge the char* string to dest, only when dest == NULL */
+#define CHARS_MERGE_NORMAL(dest, src) do { \
+    if (((dest) == NULL) && ((src) != NULL)) { \
+        (dest) = strdup((src)); \
+    } \
+} while (0)
+
+/* merge the char* string to dest, only when dest == NULL,
+   pointer is moved instead of strdup */
+#define CHARS_MERGE_MOVE(dest, src) do { \
+    if (((dest) == NULL) && ((src) != NULL)) { \
+        (dest) = (src); \
+        (src) = NULL; \
+    } \
+} while (0)
+
+/* merge the value, only when dest == default */
+#define NUM_MERGE(dest, src, default) do { \
+    if ((dest) == (default)) { \
+        (dest) = (src); \
+    } \
+} while (0)
+
+/* this macro may cause "p" to be excuted twice if it is a function */
+#define SAFE_STRDUP(p) (p) == NULL ? NULL : strdup(p);
+
+/* this macro make sure "src" to be excuted once if it is function, so it is
+   safe for functions that have state logged, such as "strtok" */
+#define SAFE_STRDUP_WITH_FUNC(dest, src, iter) do { \
+    (iter) = (src); \
+    if ((iter) == NULL) { \
+        (dest) = NULL; \
+    } else { \
+       (dest) = strdup((iter)); \
+    } \
+} while (0)
+
+/* array version of SAFE_STRDUP, dest and src are char**. */
+#define SAFE_PSTR_ARRAY_DUP(ppdest, dest_num, ppsrc, src_num, iter) do { \
+    (dest_num) = (src_num); \
+    (ppdest) = NULL; \
+    if (((ppsrc) != NULL) && ((src_num) > 0)) { \
+        SAFE_CALLOC((ppdest), (src_num), sizeof(char *)); \
+        (iter) = 0; \
+        while ((iter) < (src_num)) { \
+            *((ppdest)+(iter)) = SAFE_STRDUP(*((ppsrc)+(iter))); \
+            (iter)++; \
+        } \
+    } \
+} while (0)
+
+/* this function would sort the pqos and check its values. */
+int vlan_8021q_qos_check_valid(VLAN_Qos_8021q *pqos);
+
+/* converting qos string of 802.1.Q, it should be as "0:0 1:0 2:0" */
+DLL_PUBLIC int vlan_8021q_qos_str_to_num(VLAN_Qos_8021q *pqos, const char *str);
+DLL_PUBLIC int vlan_8021q_qos_num_to_str(char **str, const VLAN_Qos_8021q *pqos);
+
+/* following functions would return string by malloc, so it need free later */
+char *combine_file_name(const char *prefix, const char *name);
+
+/* translate the iffstate to simple down or up, because orginal state is
+   complex for history reason in linux kernel */
+DLL_PUBLIC int get_simple_state(struct EthIface *piface);
+
+/* err message number to char* */
+char *translate_error_no(int errno);
+
+#endif
-- 
1.7.1





More information about the Libvirt-cim mailing list