[Libvirt-cim] [V4 PATCH 3/8] vlan library - add a simple implemention for bridge

Sharad Mishra snmishra at us.ibm.com
Thu Jan 19 19:06:57 UTC 2012


libvirt-cim-bounces at redhat.com wrote on 01/18/2012 01:42:00 AM:

> Wenchao Xia <xiawenc at linux.vnet.ibm.com>
> Sent by: libvirt-cim-bounces at redhat.com
>
> 01/18/2012 01:42 AM
>
> Please respond to
> List for discussion and development of libvirt CIM
<libvirt-cim at redhat.com>
>
> To
>
> libvirt-cim at redhat.com
>
> cc
>
> Wenchao Xia <xiawenc at 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 at 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 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 <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 at redhat.com
> https://www.redhat.com/mailman/listinfo/libvirt-cim
>




More information about the Libvirt-cim mailing list