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

Wayne Xia xiawenc at linux.vnet.ibm.com
Fri Jan 20 01:52:07 UTC 2012


Thank u for reviewing my codes.:)

于 2012-1-20 3:06, Sharad Mishra 写道:
>
> 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?
>
my mistake, errno did not need to be returned.

>> +    }
>> +    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) {
>

right.

>> +        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?
>
the pointer have beed added to struct EthIface, so un-init function
of EthIface would free it.


>> +            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
>>
>
> _______________________________________________
> Libvirt-cim mailing list
> Libvirt-cim at redhat.com
> https://www.redhat.com/mailman/listinfo/libvirt-cim
>


-- 
Best Regards

Wayne Xia
mail:xiawenc at linux.vnet.ibm.com
tel:86-010-82450803




More information about the Libvirt-cim mailing list