| /* |
| * |
| * 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; |
| } |