libvirt-cim-bounces(a)redhat.com wrote on 01/18/2012 01:42:00 AM:
Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
Sent by: libvirt-cim-bounces(a)redhat.com
01/18/2012 01:42 AM
Please respond to
List for discussion and development of libvirt CIM
<libvirt-cim(a)redhat.com>
To
libvirt-cim(a)redhat.com
cc
Wenchao Xia <xiawenc(a)cn.ibm.com>
Subject
[Libvirt-cim] [V4 PATCH 3/8] vlan library - add a simple
implemention for bridge
This patch use ioctl to get bridge settings from kernel. Netlink
protocol
can't be used for bridge in linux2.6 kernel.
ioctl is the oldest way to talk to kernel about bridge, so it have
some
limit in the ports number and bridge number. Currently they are set
to
1024.
Signed-off-by: Wenchao Xia <xiawenc(a)cn.ibm.com>
---
libnetwork/host_network_implement_bridge.c | 224 +++++++++++++++++
+++++++++++
libnetwork/host_network_implement_bridge.h | 8 +
2 files changed, 232 insertions(+), 0 deletions(-)
create mode 100644 libnetwork/host_network_implement_bridge.c
create mode 100644 libnetwork/host_network_implement_bridge.h
diff --git a/libnetwork/host_network_implement_bridge.c b/
libnetwork/host_network_implement_bridge.c
new file mode 100644
index 0000000..39c6b13
--- /dev/null
+++ b/libnetwork/host_network_implement_bridge.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * Authors:
+ * Wenchao Xia <xiawenc(a)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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <net/if.h>
+#include <linux/if_bridge.h>
+#include <sys/ioctl.h>
+
+#include "host_network_implement_bridge.h"
+#include "host_network_helper.h"
+#include "host_network_error.h"
+
+/* following number can't be changed otherwise ioctl get errors */
+#define BR_NUM_MAX 1024
+#define PORT_NUM_MAX 1024
+#define NAME_BUFF_SIZE 16
+
+static int socket_br = -1;
+
+static int try_socket_init(void)
+{
+ if (socket_br < 0) {
+ if ((socket_br = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
+ return -errno;
Why return -errno?
+ }
+ return 1;
+}
+
+void try_socket_close(void)
+{
+ if (socket_br > 0) {
+ close(socket_br);
+ socket_br = -1;
+ }
+}
+
+static int get_bridge_ports(EthIface *piface)
+{
+ struct ifreq req;
+ char ifname[NAME_BUFF_SIZE];
+ int if_indexes[PORT_NUM_MAX];
+ unsigned long args[4];
+ int i, ret = ERR_LIBBR;
+ BR_Prop *pbr;
+
+ memset(ifname, 0, sizeof(ifname));
+ memset(&req, 0 ,sizeof(req));
+ memset(if_indexes, 0 ,sizeof(if_indexes));
+ args[0] = BRCTL_GET_PORT_LIST;
+ args[1] = (unsigned long)if_indexes;
+ args[2] = PORT_NUM_MAX;
+ args[3] = 0;
+
+ strncpy(req.ifr_name, piface->name, NAME_BUFF_SIZE);
+ req.ifr_data = (char *) &args;
+
+ if (0 > ioctl(socket_br, SIOCDEVPRIVATE, &req)) {
convention used by libvirt-cim is - if (ioctl(socket_br, SIOCDEVPRIVATE,
&req) > 0) {
+ CU_DEBUG("failed in ioctl listing ports of bridge
%s,"
+ " errno %d, reason %s.",
+ piface->name, errno, strerror(errno));
+ goto out;
+ }
+
+ if (piface->pbr_prop == NULL) {
+ eth_iface_add_br_prop(piface);
+ }
+ pbr = piface->pbr_prop;
+
+ i = -1;
+ while (i < PORT_NUM_MAX) {
+ i++;
+ if (if_indexes[i] <= 0) {
+ continue;
+ }
+ if (0 == if_indextoname(if_indexes[i], ifname)) {
same as above
+ CU_DEBUG("failed to translate if_index %d, skip
it.",
if_indexes);
+ continue;
+ }
+ /* add the ports to the list */
+ if (pbr->port_names == NULL) {
+ SAFE_CALLOC(pbr->port_names,
+ MAX_IFACE_NUM, sizeof(char *));
Where do we free this memory?
+ pbr->port_num = 0;
+ }
+ if (pbr->port_num >= MAX_IFACE_NUM) {
+ CU_DEBUG("bridge [%s] have too much eth attached!",
piface->name);
+ ret = ERR_DEVICE_EXCEED_MAXNUM;
+ goto out;
+ }
+ pbr->port_names[pbr->port_num] = SAFE_STRDUP(ifname);
+ pbr->port_num++;
+ }
+
+ ret = 1;
+
+ out:
+ return ret;
+}
+
+static int get_bridge_info(EthIface *piface)
+{
+ struct ifreq req;
+ struct __bridge_info binfo;
+ unsigned long args[4];
+ int ret = ERR_LIBBR;
+
+ memset(&req, 0, sizeof(req));
+ memset(&binfo, 0, sizeof(binfo));
+ args[0] = BRCTL_GET_BRIDGE_INFO;
+ args[1] = (unsigned long) &binfo;
+ args[2] = 0;
+ args[3] = 0;
+ req.ifr_data = (char *) &args;
+
+ if (piface->name == NULL) {
+ CU_DEBUG("bridge name not set for ioctl.");
+ goto out;
+ }
+ strncpy(req.ifr_name, piface->name, NAME_BUFF_SIZE);
+ if (ioctl(socket_br, SIOCDEVPRIVATE, &req) < 0) {
+ CU_DEBUG("failed to get info for %s, errno %d, reason %s.",
+ piface->name, errno, strerror(errno));
+ goto out;
+ }
+
+ if (piface->pbr_prop == NULL) {
+ eth_iface_add_br_prop(piface);
+ }
+ piface->pbr_prop->STP = binfo.stp_enabled;
+
+ ret = 1;
+
+ out:
+ return ret;
+}
+
+static int list_bridges(EthIfacesList *plist)
+{
+ int if_indexes[BR_NUM_MAX];
+ unsigned long args[3];
+ int brnum;
+ int i, ret = ERR_LIBBR;
+ EthIface tface;
+
+ eth_iface_init(&tface);
+ SAFE_CALLOC(tface.name, NAME_BUFF_SIZE, 1);
free?
+
+ args[0] = BRCTL_GET_BRIDGES;
+ args[1] = (unsigned long)if_indexes;
+ args[2] = BR_NUM_MAX;
+ memset(if_indexes, 0, sizeof(if_indexes));
+
+ if (0 > try_socket_init()) {
convention
+ CU_DEBUG("failed to init socket for bridge
ioctl,"
+ " errno is %d, reason: %s.",
+ errno, strerror(errno));
+ goto out;
+ }
+
+ brnum = ioctl(socket_br, SIOCGIFBR, args);
+ if (brnum < 0) {
+ CU_DEBUG("failed tp get bridge, errno is %d, reason: %s.",
+ errno, strerror(errno));
+ goto out;
+ }
+
+ i = 0;
+ while (i < brnum) {
+ if (!if_indextoname(if_indexes[i], tface.name)) {
+ CU_DEBUG("failed to translate index %d, errno is %d,
reason: %s.",
+ if_indexes[i], errno, strerror(errno));
+ goto out;
+ }
+
+ ret = get_bridge_info(&tface);
+ if (ret != 1) {
+ CU_DEBUG("failed to get info for %s.", tface.name);
+ continue;
+ }
+
+ ret = get_bridge_ports(&tface);
+ if (ret != 1) {
+ CU_DEBUG("failed to get info for %s.", tface.name);
+ continue;
+ }
+
+ if (1 != eth_ifaceslist_add(plist, &tface)) {
convention
+ CU_DEBUG("failed to add device to list.");
+ goto out;
+ }
+ eth_iface_uninit(&tface);
+ eth_iface_init(&tface);
+ SAFE_CALLOC(tface.name, NAME_BUFF_SIZE, 1);
free?
+ i++;
+ }
+ ret = 1;
+
+ out:
+ eth_iface_uninit(&tface);
+ try_socket_close();
+ return ret;
+
+}
+
+int get_host_eth_ifaces_osapi_bridge(EthIfacesList *plist)
+{
+ return list_bridges(plist);
+}
diff --git a/libnetwork/host_network_implement_bridge.h b/
libnetwork/host_network_implement_bridge.h
new file mode 100644
index 0000000..ed77195
--- /dev/null
+++ b/libnetwork/host_network_implement_bridge.h
@@ -0,0 +1,8 @@
+#ifndef HOST_NETWORK_IMPLE_BRIDGE_H
+#define HOST_NETWORK_IMPLE_BRIDGE_H
+
+#include "host_network_basic.h"
+
+int get_host_eth_ifaces_osapi_bridge(EthIfacesList *plist);
+
+#endif
--
1.7.1
_______________________________________________
Libvirt-cim mailing list
Libvirt-cim(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvirt-cim