blob: 3e15d8a68d483992afced27400197cfcda3061bd [file] [log] [blame]
/*
*
* Copyright (C) 2007 Mindspeed Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "cmm.h"
#include "itf.h"
#include "fpp.h"
#include "cmmd.h"
#include <string.h>
#if 0
#include <linux/sockios.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <net/if.h>
#endif
#include <net/if_arp.h>
#if 0
static int macvlan_get_phys_interface(struct interface *itf, struct interface **phy_itf)
{
struct interface *pitf = itf;
while(1) {
if (pitf->ifindex == pitf->phys_ifindex) {
if (phy_itf != NULL)
*phy_itf = pitf;
return pitf->ifindex;
}
pitf = __itf_get(pitf->phys_ifindex);
if (pitf == NULL)
break;
}
return -1;
}
#endif
/*********************************************************************
* __cmmGetMacVlan:
*
********************************************************************/
void __cmmGetMacVlan(int fd, struct interface *itf, unsigned char *pInfoKind )
{
itf->itf_flags &= ~ITF_MACVLAN;
if ( ! strncmp( (const char *)pInfoKind, INFO_KIND_MACVLAN_STR, INFO_KIND_MACVLAN_STR_LEN ) )
{
itf->itf_flags |= ITF_MACVLAN;
}
#if 0
if (!__itf_is_tunnel(itf) &&
!__itf_is_vlan(itf) &&
!__itf_is_bridge(itf->ifindex) &&
itf->type == ARPHRD_ETHER &&
itf->phys_ifindex &&
itf->phys_ifindex != itf->ifindex )
{
int ifindex ;
ifindex = macvlan_get_phys_interface(itf, NULL);
if ( ( ifindex == WAN_IFINDEX ) || ( ifindex == LAN_IFINDEX ) )
{
itf->itf_flags |= ITF_MACVLAN;
}
}
#endif
}
/*****************************************************************
* cmmFeMacVlanUpdate
*
*****************************************************************/
int cmmFeMacVlanUpdate(FCI_CLIENT *fci_handle, int fd, int request,
struct interface *itf)
{
fpp_macvlan_cmd_t cmd;
short ret;
int action;
switch (request)
{
default:
case ADD:
if ((itf->flags & FPP_PROGRAMMED) == FPP_PROGRAMMED)
goto out;
action = FPP_ACTION_REGISTER;
break;
case REMOVE:
if (!(itf->flags & FPP_PROGRAMMED))
goto out;
action = FPP_ACTION_DEREGISTER;
break;
}
memset(&cmd, 0, sizeof(cmd));
cmd.action = action;
if (____itf_get_name(itf, cmd.macvlan_ifname, sizeof(cmd.macvlan_ifname)) < 0)
{
cmm_print(DEBUG_ERROR, "%s: ____itf_get_name(%d) failed\n", __func__, itf->ifindex);
goto err;
}
/* Get parent interface name */
if (__itf_get_name(itf->phys_ifindex , cmd.macvlan_phy_ifname, sizeof(cmd.macvlan_phy_ifname)) < 0)
{
cmm_print(DEBUG_ERROR, "%s: __itf_get_name(%d) failed\n", __func__, itf->phys_ifindex);
goto err;
}
memcpy(cmd.macaddr, itf->macaddr, itf->macaddr_len);
switch (action)
{
case FPP_ACTION_REGISTER:
cmm_print(DEBUG_COMMAND, "Send FPP_CMD_MACVLAN_ENTRY FPP_ACTION_REGISTER\n");
ret = fci_write(fci_handle, FPP_CMD_MACVLAN_ENTRY, sizeof(fpp_macvlan_cmd_t), (unsigned short *) &cmd);
if ((ret == FPP_ERR_OK) || (ret == FPP_ERR_MACVLAN_ENTRY_ALREADY_REGISTERED))
{
cmm_print(DEBUG_COMMAND, "Send FPP_CMD_MACVLAN_ENTRY FPP_ACTION_REGISTER: success\n");
itf->flags |= FPP_PROGRAMMED;
//itf->flags &= ~FPP_NEEDS_UPDATE; FIXME
}
else
{
cmm_print(DEBUG_ERROR, "%s: Error %d while sending FPP_CMD_MACVLAN_ENTRY, FPP_ACTION_REGISTER\n", __func__, ret);
goto err;
}
break;
case FPP_ACTION_DEREGISTER:
cmm_print(DEBUG_COMMAND, "Send FPP_CMD_MACVLAN_ENTRY FPP_ACTION_DEREGISTER\n");
ret = fci_write(fci_handle, FPP_CMD_MACVLAN_ENTRY, sizeof(fpp_macvlan_cmd_t), (unsigned short *) &cmd);
if ((ret == FPP_ERR_OK) || (ret == FPP_ERR_MACVLAN_ENTRY_NOT_FOUND))
{
cmm_print(DEBUG_COMMAND, "Send FPP_CMD_MACVLAN_ENTRY FPP_ACTION_DEREGISTER: success\n");
itf->flags &= ~FPP_PROGRAMMED;
}
else
{
cmm_print(DEBUG_ERROR, "%s: Error %d while sending FPP_CMD_MACVLAN_ENTRY, FPP_ACTION_DEREGISTER\n", __func__, ret);
goto err;
}
break;
default:
cmm_print(DEBUG_ERROR, "%s: unknown FPP_CMD_MACVLAN_ENTRY action %x\n", __func__, action);
break;
}
out:
return 0;
err:
return -1;
}
/*******************************************************************
* cmmMacVlanQuery
*
*******************************************************************/
int cmmMacVlanQueryProcess(char **keywords, int tabStart, daemon_handle_t daemon_handle)
{
int rcvBytes = 0;
char rcvBuffer[256];
short rc;
int count = 0;
cmmd_macvlan_cmd_t* pMacVlanCmd = (cmmd_macvlan_cmd_t *) rcvBuffer;
pMacVlanCmd->action = CMMD_ACTION_QUERY;
rcvBytes = cmmSendToDaemon(daemon_handle, CMMD_CMD_MACVLAN_ENTRY, pMacVlanCmd,
sizeof(cmmd_macvlan_cmd_t) , rcvBuffer);
if (rcvBytes < (int)sizeof(cmmd_macvlan_cmd_t) ) {
rc = (rcvBytes < sizeof(unsigned short) ) ? 0 :
*((unsigned short *) rcvBuffer);
if (rc == CMMD_ERR_UNKNOWN_ACTION) {
cmm_print(DEBUG_STDERR,
"ERROR: FPP MACVLAN does not support CMMD_ACTION_QUERY\n");
} else if (rc == CMMD_ERR_MACVLAN_ENTRY_NOT_FOUND) {
cmm_print(DEBUG_STDERR, "ERROR: FPP MACVLAN table empty\n");
} else {
cmm_print(DEBUG_STDERR,
"ERROR: Unexpected result returned from FPP rc:%d\n", rc);
}
return CLI_OK;
}
cmm_print(DEBUG_STDOUT, "MACVLAN interfaces:\n");
do {
cmm_print(DEBUG_STDOUT, "Interface: %s, Physical Interface: %s HWaddr: %02x:%02x:%02x:%02x:%02x:%02x \n", pMacVlanCmd->macvlan_ifname, pMacVlanCmd->macvlan_phy_ifname,
pMacVlanCmd->macaddr[0],pMacVlanCmd->macaddr[1],
pMacVlanCmd->macaddr[2],pMacVlanCmd->macaddr[3],
pMacVlanCmd->macaddr[4],pMacVlanCmd->macaddr[5]);
count++;
pMacVlanCmd->action = CMMD_ACTION_QUERY_CONT;
rcvBytes = cmmSendToDaemon(daemon_handle, CMMD_CMD_MACVLAN_ENTRY, pMacVlanCmd,
sizeof(cmmd_macvlan_cmd_t) , rcvBuffer);
}while (rcvBytes >= sizeof(cmmd_macvlan_cmd_t) );
cmm_print(DEBUG_STDOUT, "Total MACVLAN Entries:%d\n", count);
return CLI_OK;
}
/*****************************************************************
* cmmMacVlanLocalShow
*
*
******************************************************************/
int cmmMacVlanLocalShow(struct cli_def *cli, char *command, char *argv[], int argc)
{
struct list_head *entry;
struct interface *itf;
char ifname[IFNAMSIZ], phys_ifname[IFNAMSIZ];
int i;
cli_print(cli,"MACVLAN Interfaces:");
for (i = 0; i < ITF_HASH_TABLE_SIZE; i++)
{
__pthread_mutex_lock(&itf_table.lock);
for (entry = list_first(&itf_table.hash[i]); entry != &itf_table.hash[i]; entry = list_next(entry))
{
itf = container_of(entry, struct interface, list);
if (!__itf_is_macvlan(itf))
continue;
cli_print(cli, "Interface: %s, Physical Interface: %s, HWaddr: %02x:%02x:%02x:%02x:%02x:%02x, %s", if_indextoname(itf->ifindex, ifname), if_indextoname(itf->phys_ifindex, phys_ifname), itf->macaddr[0], itf->macaddr[1], itf->macaddr[2], itf->macaddr[3], itf->macaddr[4], itf->macaddr[5], (__itf_is_up(itf)?"UP":"DOWN"));
}
__pthread_mutex_unlock(&itf_table.lock);
}
return CLI_OK;
}