Logo Search packages:      
Sourcecode: dcbd version File versions  Download package

bonding.c

/*******************************************************************************

  Intel Data Center Bridging (DCB) Software
  Copyright(c) 2007-2009 Intel Corporation.

  This program is free software; you can redistribute it and/or modify it
  under the terms and conditions of the GNU General Public License,
  version 2, as published by the Free Software Foundation.

  This program is distributed in the hope it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  more details.

  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.

  The full GNU General Public License is included in this distribution in
  the file called "COPYING".

  Contact Information:
  e1000-eedc Mailing List <e1000-eedc@lists.sourceforge.net>
  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497

*******************************************************************************/

#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if_bonding.h>
#include <linux/sockios.h>
#include "bonding.h"
#include "dcb_types.h"
#include "drv_cfg.h"


/**
 *    is_bond - check if interface is a bond interface
 *    @ifname: name of the interface
 *
 *    Returns 0 if ifname is not a bond, 1 if it is a bond.
 */
int   is_bond(char *ifname)
{
      int fd;
      struct ifreq ifr;
      ifbond ifb;
      int rval = 0;

      fd = socket(PF_INET, SOCK_DGRAM, 0);

      if (fd <= 0) {
            perror("is_bond() socket create failed");
            return 0;
      }

      memset(&ifr, 0, sizeof(ifr));
      strcpy(ifr.ifr_name, ifname);

      memset(&ifb, 0, sizeof(ifb));
      ifr.ifr_data = (caddr_t)&ifb;
      if (ioctl(fd,SIOCBONDINFOQUERY, &ifr) == 0)
            rval = 1;
      else
            rval = 0;

      close(fd);
      return rval;
}

/**
 *    is_san_mac - check if address is a san mac addr
 *    @addr: san mac address
 *
 *    Returns 0 if addr is NOT san mac, 1 if it is a san mac.
 */
int is_san_mac(u8 *addr)
{
      int i; 

      for ( i = 0; i < ETH_ALEN; i++) {
            if ( addr[i]!= 0xff )
                  return 1;
      }

      return 0;
}

/**
 *    get_src_mac_from_bond - select a source MAC to use for slave
 *    @bond_port: pointer to port structure for a bond interface
 *    @ifname: interface name of the slave port
 *    @addr: address of buffer in which to return the selected MAC address
 *
 *    Checks to see if ifname is a slave of the bond port.  If it is,
 *    then a 
 *    Returns 0 if a source MAC from the bond could not be found. 1 is
 *    returned if the slave was found in the bond.  addr is updated with
 *    the source MAC that should be used.
*/
int   get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr)
{
      int fd;
      struct ifreq ifr;
      ifbond ifb;
      ifslave ifs;
      char act_ifname[MAX_DEVICE_NAME_LEN];
      char bond_mac[ETH_ALEN], san_mac[ETH_ALEN];
      int found = 0;
      int i;

      fd = socket(PF_INET, SOCK_DGRAM, 0);

      if (fd <= 0) {
            perror("get_src_mac_from_bond failed");
            return 0;
      }

      memset(bond_mac, 0, sizeof(bond_mac));
      memset(&ifr, 0, sizeof(ifr));
      strcpy(ifr.ifr_name, bond_port->ifname);
      memset(&ifb, 0, sizeof(ifb));
      ifr.ifr_data = (caddr_t)&ifb;
      if (ioctl(fd,SIOCBONDINFOQUERY, &ifr) == 0) {
            /* get the MAC address for the current bond port */
            if (ioctl(fd,SIOCGIFHWADDR, &ifr) == 0)
                  memcpy(bond_mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
            else
                  perror("error getting bond MAC address");

            /* scan the bond's slave ports and looking for the
             * current port and the active slave port.
            */
            memset(act_ifname, 0, sizeof(act_ifname));
            for (i = 0; i < ifb.num_slaves; i++) {
                  memset(&ifs, 0, sizeof(ifs));
                  ifs.slave_id = i;
                  ifr.ifr_data = (caddr_t)&ifs;

                  if (ioctl(fd,SIOCBONDSLAVEINFOQUERY, &ifr) == 0) {
                        if (!strncmp(ifs.slave_name, ifname,
                              MAX_DEVICE_NAME_LEN))
                              found = 1;

                        if (ifs.state == BOND_STATE_ACTIVE)
                              strncpy(act_ifname, ifs.slave_name,
                                    MAX_DEVICE_NAME_LEN);
                  }
            }
      }

      /* current port is not a slave of the bond */
      if (!found) {
            close(fd);
            return 0;
      }

      /* Get slave port's current perm MAC address
       * This will be the default return value
      */
      memset(&ifr, 0, sizeof(ifr));
      strcpy(ifr.ifr_name, ifname);
      if (ioctl(fd,SIOCGIFHWADDR, &ifr) == 0) {
            memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
      }
      else {
            perror("error getting slave MAC address");
            close(fd);
            return 0;
      }

      switch (ifb.bond_mode) {
      case BOND_MODE_ACTIVEBACKUP:
            /* If current port is not the active slave, then 
             * if the bond MAC is equal to the port's
             * permanent MAC, then find and return
             * the permanent MAC of the active
             * slave port. Otherwise, return the
             * permanent MAC of the port.
            */
            if (strncmp(ifname, act_ifname, MAX_DEVICE_NAME_LEN))
                  if (get_perm_hwaddr(ifname, addr, san_mac) == 0)
                        if (!memcmp(bond_mac, addr, ETH_ALEN))
                              get_perm_hwaddr(act_ifname, addr, 
                                                san_mac);
            break;
      default:
            /* Use the current MAC of the port */
            break;
      }

      close(fd);

      return 1;
}

Generated by  Doxygen 1.6.0   Back to index