Open Ethernet Networking (OpEN) API Guide and Reference Manual  3.6.0.3
l2ol3tunnel_example.c
/*********************************************************************
*
* Copyright 2016-2018 Broadcom.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************
*
* @filename l2ol3tunnel_example.c
*
* @purpose To Test Overlay APIs
* @detail This is an example application using which you can
* exercise Overlay APIs to create and view Overlay
* configuration and status on the switch.
*
* @component DCVPN
*
* @note none
*
* @end
*
**********************************************************************/
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include "rpcclt_openapi.h"
#include "proc_util.h"
#include "openapi_common.h"
static const char cSep = ':';
static unsigned char *convertMacAddressStringIntoByte
(const char *pszMACAddress, unsigned char *pbyAddress)
{
int iCounter;
for (iCounter = 0; iCounter < 6; ++iCounter)
{
unsigned int iNumber = 0;
char ch;
//Convert letter into lower case.
ch = toupper (*pszMACAddress++);
if ((ch < '0' || ch > '9') && (ch < 'A' || ch > 'F'))
{
return NULL;
}
//Convert into number.
// a. If character is digit then ch - '0'
// b. else (ch - 'a' + 10) it is done
// because addition of 10 takes correct value.
iNumber = isdigit (ch) ? (ch - '0') : (ch - 'A' + 10);
ch = toupper (*pszMACAddress);
if ((iCounter < 5 && ch != cSep) || (iCounter == 5 && ch != '\0' && !isspace (ch)))
{
++pszMACAddress;
if ((ch < '0' || ch > '9') && (ch < 'A' || ch > 'F'))
{
return NULL;
}
iNumber <<= 4;
iNumber += isdigit (ch) ? (ch - '0') : (ch - 'A' + 10);
ch = *pszMACAddress;
if (iCounter < 5 && ch != cSep)
{
return NULL;
}
}
/* Store result. */
pbyAddress[iCounter] = (unsigned char) iNumber;
/* Skip cSep. */
++pszMACAddress;
}
return pbyAddress;
}
const char *openapiErrorStrGet (open_error_t error)
{
char *name = "";
switch (error)
{
name = "OPEN_E_NONE";
break;
case OPEN_E_RPC:
name = "OPEN_E_RPC";
break;
name = "OPEN_E_INTERNAL";
break;
name = "OPEN_E_PARAM";
break;
name = "OPEN_E_FULL";
break;
name = "OPEN_E_EXISTS";
break;
name = "OPEN_E_TIMEOUT";
break;
name = "OPEN_E_FAIL";
break;
name = "OPEN_E_DISABLED";
break;
name = "OPEN_E_UNAVAIL";
break;
name = "OPEN_E_NOT_FOUND";
break;
name = "OPEN_E_EMPTY";
break;
name = "OPEN_E_ERROR";
break;
default:
name = "Unknown or Undefined Error";
break;
}
return name;
}
/*****************************************************************/
void add_l2Entry ( openapiClientHandle_t * clientHandle,
uint32_t tenant,
unsigned char *macAddr,
uint32_t destIntfHandle )
{
open_buffdesc macAddrBuf;
open_error_t retVal;
macAddrBuf.pstart = (char *) macAddr;
macAddrBuf.size = 6;
retVal = openapiL2oL3TenantL2FwdEntryAdd (clientHandle, tenant, &macAddrBuf, destIntfHandle);
if (retVal != OPEN_E_NONE)
{
printf ("L2 entry add failed, rc=%s\n", openapiErrorStrGet (retVal));
}
else
{
printf ("L2 entry add success, rc=%s\n", openapiErrorStrGet (retVal));
}
return;
}
/*****************************************************************/
void del_l2Entry ( openapiClientHandle_t * clientHandle,
uint32_t tenant,
unsigned char *macAddr )
{
open_buffdesc macAddrBuf;
open_error_t retVal;
macAddrBuf.pstart = (char *) macAddr;
macAddrBuf.size = 6;
retVal = openapiL2oL3TenantL2FwdEntryDelete (clientHandle, tenant, &macAddrBuf);
if (retVal != OPEN_E_NONE)
{
printf ("L2 entry delete failed, rc=%s\n", openapiErrorStrGet (retVal));
}
else
{
printf ("L2 entry delete success, rc=%s\n", openapiErrorStrGet (retVal));
}
return;
}
/*****************************************************************/
void get_l2Entry (openapiClientHandle_t * clientHandle,
uint32_t tenant,
unsigned char * macAddr )
{
open_error_t retVal;
uint32_t count = 0;
char macAddress[OPEN_MAC_ADDR_LEN];
char *ptr = NULL;
open_buffdesc macAddrBuf;
memcpy (macAddress, macAddr, OPEN_MAC_ADDR_LEN);
macAddrBuf.pstart = (char *) macAddress;
macAddrBuf.size = OPEN_MAC_ADDR_LEN;
retVal = openapiL2oL3TenantL2FwdEntryGet ( clientHandle, tenant,
&macAddrBuf, &macEntry );
if (retVal == OPEN_E_NONE)
{
printf("Found MAC entry!\n\n");
printf ("+--------------------------------------------------------+\n");
printf ("| Sl Tenant MAC Address destHandle Static |\n");
printf ("+--------------------------------------------------------+\n");
ptr = (char *)macEntry.macAddress;
printf ("| %-5u %-10d %02x:%02x:%02x:%02x:%02x:%02x %-5d %d |\n",
++count, macEntry.tenantId,
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5],
macEntry.destHandle, macEntry.isStatic );
printf ("+--------------------------------------------------------+\n");
}
else
{
printf("Failed to find MAC entry. RC=%s\n", openapiErrorStrGet(retVal));
}
return;
}
/*****************************************************************/
void get_l2Entries (openapiClientHandle_t * clientHandle,
uint32_t tenant )
{
open_error_t retVal;
uint32_t count = 0, seed = tenant;
char macAddr[OPEN_MAC_ADDR_LEN];
char *ptr = NULL;
open_buffdesc macAddrBuf;
open_l2ol3L2FwdEntry_t nextMacEntry;
memset (macAddr, 0, OPEN_MAC_ADDR_LEN);
macAddrBuf.pstart = (char *) macAddr;
macAddrBuf.size = OPEN_MAC_ADDR_LEN;
if (tenant)
{
printf ("Forwarding entries for tenant=%d:\n\n", tenant);
}
else
{
printf ("Forwarding entries in database:\n\n");
}
printf ("+--------------------------------------------------------+\n");
printf ("| Sl Tenant MAC Address destHandle Static |\n");
printf ("+--------------------------------------------------------+\n");
do
{
retVal = openapiL2oL3TenantL2FwdEntryNextGet ( clientHandle, tenant,
&macAddrBuf, &nextMacEntry );
if (retVal == OPEN_E_NONE)
{
if ( /* all */ (seed == 0) ||
/* specific tenant only */
(seed && (seed == nextMacEntry.tenantId)))
{
ptr = (char *)nextMacEntry.macAddress;
printf ("| %-5u %-10d %02x:%02x:%02x:%02x:%02x:%02x %-5d %d |\n",
++count, nextMacEntry.tenantId,
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5],
nextMacEntry.destHandle, nextMacEntry.isStatic );
}
/* get next */
tenant = nextMacEntry.tenantId;
memcpy (macAddrBuf.pstart, nextMacEntry.macAddress, OPEN_MAC_ADDR_LEN);
}
} while ((retVal == OPEN_E_NONE) && (count < 50));
printf ("+--------------------------------------------------------+\n");
return;
}
/* Display the switch overlay capabilities */
void switch_capabilities_get (openapiClientHandle_t * clientHandle)
{
open_error_t retVal;
uint32_t capabilities = 0;
retVal = openapiL2oL3TunnelCapabilitiesGet (clientHandle, &capabilities);
if (retVal != OPEN_E_NONE)
{
printf ("Switch Overlay Capabilities Get Failed. rc=%s\n",
openapiErrorStrGet (retVal));
return;
}
if (!capabilities)
{
printf ("Switch does not support Overlay Capabilities.\n");
return;
}
printf ("Switch supports below overlay types:\n");
if (capabilities & OPEN_L2OL3_TUNNEL_TYPE_VXLAN)
{
printf("\t VXLAN \n");
}
if (capabilities & OPEN_L2OL3_TUNNEL_TYPE_NVGRE)
{
printf("\t NVGRE \n");
}
return;
}
void tunnel_services_config_get (openapiClientHandle_t * clientHandle,
{
open_error_t retVal;
uint32_t udpPort = 0;
retVal = openapiL2oL3SwitchTunnelModeGet (clientHandle, tunnelType, &mode);
if (retVal != OPEN_E_NONE)
{
printf ("Overlay Configuration Mode Get Failed for Tunnel Type=%d rc=%s\n",
tunnelType, openapiErrorStrGet (retVal));
}
else
{
printf ("Overlay Configuration Mode is %s for Tunnel Type=%d. rc=%s\n",
(mode == OPEN_ENABLE ? "Enabled" : "Disabled"),
tunnelType, openapiErrorStrGet (retVal));
}
if (tunnelType != OPEN_L2OL3_TUNNEL_TYPE_VXLAN)
{
return;
}
/* Get VXLAN UDP Port Configuration */
retVal = openapiL2oL3SwitchVxlanUdpDestPortGet (clientHandle, &udpPort);
if (retVal == OPEN_E_NONE)
{
printf ("VXLAN UDP port is configured to %d.\n", udpPort);
}
else
{
printf ("VXLAN UDP port configured get has failed. rc=%s.\n",
openapiErrorStrGet (retVal));
}
return;
}
void tunnel_services_config_set (openapiClientHandle_t * clientHandle,
{
open_error_t retVal;
retVal = openapiL2oL3SwitchTunnelModeSet (clientHandle, tunnelType, mode);
if (retVal != OPEN_E_NONE)
{
printf ("Overlay Configuration Mode Set Failed for Tunnel Type=%d rc=%s\n",
tunnelType, openapiErrorStrGet (retVal));
}
else
{
printf ("Overlay Configuration Mode is set to %s for Tunnel Type=%d. rc=%s\n",
(mode == OPEN_ENABLE ? "Enable" : "Disable"),
tunnelType, openapiErrorStrGet (retVal));
}
return;
}
void tunnel_services_config_vxlan_udp_port (openapiClientHandle_t * clientHandle,
uint32_t udpPort)
{
open_error_t retVal;
retVal = openapiL2oL3SwitchVxlanUdpDestPortSet (clientHandle, udpPort);
if (retVal != OPEN_E_NONE)
{
printf ("VXLAN UDP destination port=%d configuration on Swtich failed. rc=%s\n",
udpPort, openapiErrorStrGet (retVal));
}
else
{
printf ("VXLAN UDP destination port=%d configuration on Switch is successful. rc=%s\n",
udpPort, openapiErrorStrGet (retVal));
}
return;
}
void create_tenant (openapiClientHandle_t * clientHandle,
uint32_t tenant,
uint32_t vlanId, uint32_t srcIP,
uint32_t configType)
{
open_error_t retVal;
memset (&config, 0, sizeof (config));
config.tunnelType = tunnelType;
config.vlanId = vlanId;
config.localTepIpAddr = srcIP;
retVal = openapiL2oL3TenantCreate (clientHandle, configType, tenant, config);
if (retVal == OPEN_E_NONE)
{
printf ("Tenant configuration successful\n");
}
else
{
printf ("Tenant configuration failed, rc=%s\n", openapiErrorStrGet (retVal));
}
return;
}
void display_tenants (openapiClientHandle_t * clientHandle, uint32_t tenant)
{
open_error_t retVal;
uint32_t display_count = 1;
uint32_t nextTenant = 0;
open_l2ol3TenantConfig_t nextTenantConfig;
char ipAddrString[INET_ADDRSTRLEN+1];
do
{
memset (&nextTenantConfig, 0, sizeof (nextTenantConfig));
retVal = openapiL2oL3TenantNextGet (clientHandle, tenant,
&nextTenant, &nextTenantConfig);
if (retVal == OPEN_E_NONE)
{
tenant = nextTenant;
printf (" %-8u %-8u %s %-5u %-15s \n",
display_count++,
nextTenant,
(nextTenantConfig.tunnelType == OPEN_L2OL3_TUNNEL_TYPE_VXLAN ? "VXLAN" : "NVGRE"),
nextTenantConfig.vlanId,
inet_ntop(AF_INET, &nextTenantConfig.localTepIpAddr, ipAddrString, INET_ADDRSTRLEN));
}
}
while (retVal == OPEN_E_NONE);
}
void get_tenant (openapiClientHandle_t * clientHandle, uint32_t tenant)
{
open_error_t retVal;
uint32_t count = 1;
char ipAddrString[INET_ADDRSTRLEN+1];
memset (&config, 0, sizeof (config));
if (tenant)
{
retVal = openapiL2oL3TenantGet (clientHandle, tenant, &config);
if (retVal == OPEN_E_NONE)
{
printf ("+----------------------------------------------------------------+\n");
printf (" Sl Tenant Tunnel-Type VLAN ID Local TEP \n");
printf ("+----------------------------------------------------------------+\n");
printf (" %-8u %-8u %s %-5u %-15s \n",
count++,
tenant,
(config.tunnelType == OPEN_L2OL3_TUNNEL_TYPE_VXLAN ? "VXLAN" : "NVGRE"),
config.vlanId, inet_ntop(AF_INET, &config.localTepIpAddr, ipAddrString, INET_ADDRSTRLEN));
printf ("+----------------------------------------------------------------+\n");
}
else
{
printf ("Tenant %d info get failed. rc=%s\n",
tenant, openapiErrorStrGet (retVal));
}
}
else
{
printf ("+----------------------------------------------------------------+\n");
printf (" Sl Tenant Tunnel-Type VLAN ID Local TEP \n");
printf ("+----------------------------------------------------------------+\n");
display_tenants (clientHandle, 0); /* Iterate through all */
printf ("+----------------------------------------------------------------+\n");
}
return;
}
void delete_tenant (openapiClientHandle_t * clientHandle, uint32_t tenant)
{
open_error_t retVal;
retVal = openapiL2oL3TenantDelete (clientHandle, tenant);
if (retVal == OPEN_E_NONE)
{
printf ("Tenant deleted\n");
}
else
{
printf ("Tenant deletion failed, rc=%s\n", openapiErrorStrGet (retVal));
}
return;
}
void get_access_port (openapiClientHandle_t * clientHandle, uint32_t accessId)
{
if (accessId)
{
rc = openapiL2oL3AccessPortGet (clientHandle, accessId, &accessInfo );
if (OPEN_E_NONE == rc)
{
printf("------------------------------------------------------------------------\n");
printf(" Tenant Tunnel-Type Access-Handle VLAN intIfNum Match-Type \n");
printf("------------------------------------------------------------------------\n");
printf(" %-10d %s %-4d %-4d %d %d\n",
accessInfo.tenantId,
(accessInfo.tunnelType == OPEN_L2OL3_TUNNEL_TYPE_VXLAN ? "VXLAN" : "NVGRE"),
accessInfo.accessHandle, accessInfo.vlanId,
accessInfo.intIfNum, accessInfo.matchType);
printf("------------------------------------------------------------------------\n");
}
else
{
printf("Access port identifier = %d information not found!\n", accessId);
}
}
else
{
printf(" Invalid access port identifier = %d\n", accessId);
}
}
void get_access_ports (openapiClientHandle_t * clientHandle, uint32_t tenant)
{
uint32_t count = 0;
uint32_t accessHandle = 0;
printf("------------------------------------------------------------------------\n");
printf(" Tenant Tunnel-Type Access-Handle VLAN intIfNum Match-Type \n");
printf("------------------------------------------------------------------------\n");
if (tenant)
{
do
{
rc = openapiL2oL3AccessPortNextGet (clientHandle, accessHandle, &accessInfoNext );
if (OPEN_E_NONE == rc)
{
if (tenant == accessInfoNext.tenantId)
{
printf(" %-10d %s %-4d %-4d %d %d\n",
accessInfoNext.tenantId,
(accessInfoNext.tunnelType == OPEN_L2OL3_TUNNEL_TYPE_VXLAN ? "VXLAN" : "NVGRE"),
accessInfoNext.accessHandle, accessInfoNext.vlanId,
accessInfoNext.intIfNum, accessInfoNext.matchType);
count++;
}
accessHandle = accessInfoNext.accessHandle;
}
} while (rc == OPEN_E_NONE);
printf("------------------------------------------------------------------------\n");
printf("\n\nTenant %d has %d Access Ports\n", tenant, count);
}
else
{
/* List Down all access ports of all tenants */
do
{
rc = openapiL2oL3AccessPortNextGet (clientHandle, accessHandle, &accessInfoNext );
if (OPEN_E_NONE == rc)
{
printf(" %-10d %s %-4d %-4d %d %d\n",
accessInfoNext.tenantId,
(accessInfoNext.tunnelType == OPEN_L2OL3_TUNNEL_TYPE_VXLAN ? "VXLAN" : "NVGRE"),
accessInfoNext.accessHandle, accessInfoNext.vlanId,
accessInfoNext.intIfNum, accessInfoNext.matchType);
accessHandle = accessInfoNext.accessHandle;
count++;
}
} while (rc == OPEN_E_NONE);
printf("------------------------------------------------------------------------\n");
printf("\n\nTotal Access Ports of All Tenants = %d\n", count);
}
return;
}
void create_tunnel (openapiClientHandle_t * clientHandle,
uint32_t tenant,
uint32_t remoteIP,
OPEN_L2OL3_CONFIG_t configType,
uint32_t tunnelHandle)
{
uint32_t handle;
open_error_t retVal;
handle = tunnelHandle;
retVal = openapiL2oL3TunnelCreate (clientHandle, configType, tenant, remoteIP, &handle);
if (retVal == OPEN_E_NONE)
{
printf ("Tunnel created, handle %d\n", handle);
}
else
{
printf ("Tunnel creation failed rc=%s\n", openapiErrorStrGet (retVal));
}
return;
}
void delete_tunnel (openapiClientHandle_t * clientHandle, uint32_t tunnelHandle)
{
open_error_t retVal;
retVal = openapiL2oL3TunnelDelete (clientHandle, tunnelHandle);
if (retVal == OPEN_E_NONE)
{
printf ("Tunnel deleted\n");
}
else
{
printf ("Tunnel deletion failed, rc=%s\n", openapiErrorStrGet (retVal));
}
return;
}
void get_all_tunnels (openapiClientHandle_t * clientHandle)
{
uint32_t tunnelHandle = 0, count = 0;
open_l2ol3TunnelInfo_t tunnelInfoNext;
char ipAddrString[INET_ADDRSTRLEN+1];
printf("------------------------------------------------------------------------\n");
printf(" Tenant Tunnel-Type Tunnel-Handle Remote-TEP Status Reason \n");
printf("------------------------------------------------------------------------\n");
do
{
rc = openapiL2oL3TunnelNextGet (clientHandle, tunnelHandle, &tunnelInfoNext );
if (OPEN_E_NONE == rc)
{
printf(" %-9d %s %-4d %-15s %d %d\n",
tunnelInfoNext.tenantId,
(tunnelInfoNext.tunnelType == OPEN_L2OL3_TUNNEL_TYPE_VXLAN ? "VXLAN" : "NVGRE"),
tunnelInfoNext.tunnelHandle,
inet_ntop(AF_INET, &tunnelInfoNext.remoteIPAddr, ipAddrString, INET_ADDRSTRLEN),
(tunnelInfoNext.status.status == OPEN_LINK_UP ? 1 : 0),
tunnelInfoNext.status.reasonFlags);
tunnelHandle = tunnelInfoNext.tunnelHandle;
count++;
}
}
while (rc == OPEN_E_NONE);
printf("------------------------------------------------------------------------\n");
printf("\n\nTotal Tenant Tunnels = %d\n", count);
}
void resource_stats_get(openapiClientHandle_t * clientHandle)
{
open_error_t retVal;
retVal = openapiL2oL3ResourceLimitsGet (clientHandle, &resourceLimits);
if (retVal != OPEN_E_NONE)
{
printf("\n\nERROR: Failed to get resource limits. RC=%s\n\n", openapiErrorStrGet(retVal));
return;
}
/* Dump resource limits */
printf("\n\n<<<<< RESOURCE ALLOWED LIMITS >>>>>\n\n");
printf("Maximum Number of Tenants Allowed : %d\n", resourceLimits.maxNumTenants);
printf("Maximum Number of Access Ports Allowed : %d\n", resourceLimits.maxNumAccessPorts);
printf("Maximum Number of Tenant Tunnels Allowed : %d\n", resourceLimits.maxNumTunnelPorts);
printf("Maximum Number of Shared Tunnels Allowed : %d\n", resourceLimits.maxNumTunnelsInHw);
printf("Maximum Number of User configured host \n"
"entries allowed per Physical/Lag Interface : %d\n", resourceLimits.maxNumLocalStaticFwdEntriesPerInterface);
printf("Maximum Number of User configured host \n"
"entries allowed per Tenant : %d\n", resourceLimits.maxNumRemoteStaticFwdEntriesPerTenant);
printf("Maximum Number of User configured host \n"
"entries allowed on Switch : %d\n", resourceLimits.maxNumRemoteStaticFwdEntriesPerSwitch);
printf("Overlay forwarding database size : %d\n", resourceLimits.maxNumFwdEntries);
/* Get current resource usage stats */
retVal = openapiL2oL3ResourceStatsGet (clientHandle, &resourceUsage);
if (retVal != OPEN_E_NONE)
{
printf("\n\nERROR: Failed to get resource limits. RC=%s\n\n", openapiErrorStrGet(retVal));
return;
}
printf("\n\n<<<<< RESOURCE USAGE STATISTICS >>>>>\n\n");
printf("Number of Tenants Configured : %d\n", resourceUsage.numTenants);
printf("Number of Tenant VLANs Configured : %d\n", resourceUsage.numTenantVlans);
printf("Number of Source TEPs Configured : %d\n", resourceUsage.numTenantLocalTeps);
printf("Number of Access Ports Configured : %d\n", resourceUsage.numAccessPorts);
printf("Number of Tenant Tunnels Configured : %d\n", resourceUsage.numTenantTunnels);
printf("Number of Forwarding Entries Learnt : %d\n", resourceUsage.numLearnedFwdEntries);
printf("Number of Entries Configured by User : %d\n", resourceUsage.numStaticFwdEntries);
printf("Total Forwarding Entries in Database : %d\n", resourceUsage.numTotalFwdEntries);
printf("\n\n<<<<< SOFTWARE ERROR STATISTICS >>>>>\n\n");
printf("globalTunnelModeFailures : %d\n", resourceUsage.errStats.globalTunnelModeFailures);
printf("numTenantCreateFailures : %d\n", resourceUsage.errStats.numTenantCreateFailures);
printf("numTenantDeleteFailures : %d\n", resourceUsage.errStats.numTenantDeleteFailures);
printf("numTenantVlanAddFailures : %d\n", resourceUsage.errStats.numTenantVlanAddFailures);
printf("numTenantVlanDeleteFailures : %d\n", resourceUsage.errStats.numTenantVlanDeleteFailures);
printf("numTenantSrcTepAddFailures : %d\n", resourceUsage.errStats.numTenantSrcTepAddFailures);
printf("numTenantSrcTepDeleteFailures : %d\n", resourceUsage.errStats.numTenantSrcTepDeleteFailures);
printf("numAccessCreateFailures : %d\n", resourceUsage.errStats.numAccessCreateFailures);
printf("numAccessDeleteFailures : %d\n", resourceUsage.errStats.numAccessDeleteFailures);
printf("numTenantTunnelCreateFailures : %d\n", resourceUsage.errStats.numTenantTunnelCreateFailures);
printf("numTenantTunnelModifyFailures : %d\n", resourceUsage.errStats.numTenantTunnelModifyFailures);
printf("numTenantTunnelDeleteFailures : %d\n", resourceUsage.errStats.numTenantTunnelDeleteFailures);
printf("numVxlanUdpDstCfgFailures : %d\n", resourceUsage.errStats.numVxlanUdpDstCfgFailures);
printf("numStaticFwdAddFailures : %d\n", resourceUsage.errStats.numStaticFwdAddFailures);
printf("numStaticFwdDeleteFailures : %d\n", resourceUsage.errStats.numStaticFwdDeleteFailures);
printf("numLearnedFwdAddFailures : %d\n", resourceUsage.errStats.numLearnedFwdAddFailures);
printf("numLearnedFwdDeleteFailures : %d\n", resourceUsage.errStats.numLearnedFwdDeleteFailures);
return;
}
void get_tunnel_status (openapiClientHandle_t * clientHandle, uint32_t tunnelHandle)
{
open_error_t retVal;
retVal = openapiL2oL3TunnelGet (clientHandle, tunnelHandle, &tunnelInfo);
if (retVal == OPEN_E_NONE)
{
printf ("Tunnel Status:\n");
printf (" State - %s\n", ((tunnelInfo.status.status == OPEN_LINK_UP) ? "UP" : "DOWN"));
switch (tunnelInfo.status.reasonFlags)
{
printf (" Reason - INITIATOR_NOT_RESOLVED\n");
break;
printf (" Reason - INITIATOR_INSTALL_FAILED\n");
break;
printf (" Reason - TERMINATOR_INSTALL_FAILED\n");
break;
default:
printf (" Reason - None\n");
break;
}
printf ("\nTunnel status get success, rc=%s\n", openapiErrorStrGet (retVal));
}
else
{
printf ("Tunne status get failed, rc=%s\n", openapiErrorStrGet (retVal));
}
return;
}
void tunnel_stats_get (openapiClientHandle_t * clientHandle, uint32_t tunnelHandle)
{
open_error_t retVal;
memset (&tunnelStats, 0, sizeof (tunnelStats));
retVal = openapiL2oL3TunnelCounterGet (clientHandle, tunnelHandle, &tunnelStats);
if (retVal == OPEN_E_NONE)
{
printf ("Tunnel counters for handle=%d:\n", tunnelHandle);
printf ("rxPackts = %u\n", tunnelStats.rxPkts);
printf ("rxBytes = %u\n", tunnelStats.rxBytes);
printf ("txPackts = %u\n", tunnelStats.txPkts);
printf ("txBytes = %u\n", tunnelStats.txBytes);
printf ("\nTunnel counters get success, rc=%s\n", openapiErrorStrGet (retVal));
}
else
{
printf ("Tunnel counters get failed, rc=%s\n", openapiErrorStrGet (retVal));
}
return;
}
void tunnel_stats_clear (openapiClientHandle_t * clientHandle, uint32_t tunnelHandle)
{
open_error_t retVal;
retVal = openapiL2oL3TunnelCounterClear (clientHandle, tunnelHandle);
if (retVal == OPEN_E_NONE)
{
printf ("Tunnel counters clear success. rc=%s\n", openapiErrorStrGet (retVal));
}
else
{
printf ("Tunnel counters clear failed, rc=%s\n", openapiErrorStrGet (retVal));
}
return;
}
/*****************************************************************/
void printUsage (char *app)
{
printf ("Usage: %s -o <option> -g -d -c <config flags>"
" -t <tenant> -y <tunnel Type> -v <vlanId>"
" -s <srcIP> -r <remoteIP> -u <tunnel Id> -i <access Id>"
" -h \n", app);
printf ("\n");
printf ("\t o \t option should be one of the following based on action desired, \n");
printf ("\t\t config - to initialize required overlay service. \n"
"\t\t options needed to enable: -y [-p] \n"
"\t\t options needed to disable: -d -y \n"
"\t\t options needed to get: -g [-y] \n");
printf ("\t\t tenant - to perform tenant configuration and retrive status. \n"
"\t\t options needed to create/modify: -c -t -y <[-v] | [-s]> \n"
"\t\t options needed to delete: -d -t \n"
"\t\t options needed to get: -g [-t ] \n");
printf ("\t\t access - to get configured access ports information. \n"
"\t\t options needed to get: -g [-t | -i] \n");
printf ("\t\t tunnel - to perform tunnel configuration and fetch status. \n"
"\t\t options needed to create: -c -t -r \n"
"\t\t options needed to delete: -d -u \n"
"\t\t options needed to get: -g [-u] \n");
printf ("\t\t l2entry - to configure and list bridging entries. \n");
printf ("\t\t options needed to create: -t -m <[-i] | [-u]> \n");
printf ("\t\t options needed to delete: -t -m -d \n");
printf ("\t\t options needed to get: -g [-t -m | -t] \n");
printf ("\t\t stats - to get stats or clear tunnel counters. \n"
"\t\t to get tunnel stats : -g [-u] \n"
"\t\t to clear tunnel stats : -d -u \n"
"\t\t Note: to get global usage & error stats: -g \n");
printf ("\t c \t Configuration flags. (%d-Create, %d-Modify) \n",
printf ("\t d \t To delete configuration. \n");
printf ("\t g \t To fetch configuration/status. \n");
printf ("\t h \t Usage help. \n");
printf ("\t i \t Access Interface Handle. \n");
printf ("\t m \t MAC Address (xx:xx:xx:xx:xx:xx). \n");
printf ("\t p \t VXLAN destination UDP port number. \n");
printf ("\t r \t IP address of Remote TEP (Tunnel end point) in a.b.c.d format. \n");
printf ("\t s \t IP address of Source TEP or Local Gateway in a.b.c.d format. \n");
printf ("\t t \t Tenant Id (VNID for VXLAN;VSID for NVGRE). Range: %d-%d. \n",
printf ("\t u \t Tunnel handle. \n");
printf ("\t v \t VLAN Identifier or Tenant VLAN. \n");
printf ("\t y \t Tenant or Tunnel type.(VXLAN - %d, NVGRE - %d) \n",
OPEN_L2OL3_TUNNEL_TYPE_VXLAN, OPEN_L2OL3_TUNNEL_TYPE_NVGRE);
}
/*****************************************************************/
int main (int argc, char **argv)
{
openapiClientHandle_t clientHandle;
open_error_t result;
open_buffdesc switch_os_revision;
char switch_os_revision_string[100];
uint32_t tenant = 0, accessIntfNum = 0, vlanId = 0;
uint32_t configFlags = 0;
uint32_t tunnel_type = 0;
uint32_t remoteIP = 0, srcIP = 0, tunnelHandle = 0;
uint32_t dstUdp = 0;
uint32_t l2DestIntf = 0;
unsigned char macAddr[6];
unsigned char nullMac[6];
int c;
int addFlag = 1;
int getFlag = 0;
int udpFlag = 0;
int macFlag = 0;
char option_name[80] = {0};
int option_len;
l7proc_crashlog_register ();
/* Register with OpEN */
if ((result = openapiClientRegister ("direct host add", &clientHandle)) != OPEN_E_NONE)
{
printf ("\nFailed to initialize RPC to OpEN. Exiting (result = %d)\n", result);
exit (2);
}
/* RPC call can fail until server starts. Keep trying */
while (openapiConnectivityCheck (&clientHandle) != OPEN_E_NONE)
{
sleep (1);
}
L7PROC_LOGF (L7PROC_LOG_SEVERITY_INFO, 0, "Starting Overlay API example application (%s)", argv[0]);
printf ("\n");
switch_os_revision.pstart = switch_os_revision_string;
switch_os_revision.size = sizeof (switch_os_revision_string);
if (openapiNetworkOSVersionGet (&clientHandle, &switch_os_revision) == OPEN_E_NONE)
{
printf ("Network OS version = %s\n", switch_os_revision_string);
}
else
{
printf ("Network OS version retrieve error\n");
}
/* Start the tunnel cmd handler */
opterr = 0;
memset (nullMac, 0, sizeof (nullMac));
while ((c = getopt (argc, argv, "hdgy:c:v:t:m:o:i:r:s:u:p:")) != -1)
{
switch (c)
{
case 't':
tenant = atoi (optarg);
break;
case 'u':
tunnelHandle = atoi (optarg);
break;
case 'i':
accessIntfNum = atoi (optarg);
break;
case 'v':
vlanId = atoi (optarg);
break;
case 'c':
configFlags = atoi (optarg);
break;
case 'y':
tunnel_type = atoi (optarg);
break;
case 'p':
dstUdp = atoi (optarg);
udpFlag = 1;
break;
case 'r':
inet_pton (AF_INET, optarg, &remoteIP);
remoteIP = ntohl(remoteIP);
break;
case 's':
inet_pton (AF_INET, optarg, &srcIP);
srcIP = ntohl(srcIP);
break;
case 'm':
convertMacAddressStringIntoByte (optarg, macAddr);
macFlag = 1;
break;
case 'd':
addFlag = 0;
break;
case 'g':
getFlag = 1;
break;
case 'o':
strncpy (option_name, optarg, (sizeof(option_name) - 1));
break;
case 'h':
printUsage (argv[0]);
return 0;
case '?':
if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
return 1;
default:
abort ();
}
}
printf ("\n");
option_len = strlen (option_name);
if ((memcmp (option_name, "config", option_len) == 0) &&
(option_len == strlen ("config")))
{
if (getFlag)
{
switch_capabilities_get (&clientHandle);
if (tunnel_type)
{
tunnel_services_config_get (&clientHandle, tunnel_type);
}
}
else if (addFlag && tunnel_type)
{
tunnel_services_config_set (&clientHandle, tunnel_type, OPEN_ENABLE);
if (udpFlag)
{
tunnel_services_config_vxlan_udp_port (&clientHandle, dstUdp);
}
}
else if (tunnel_type)
{
tunnel_services_config_set (&clientHandle, tunnel_type, OPEN_DISABLE);
}
else
{
printUsage (argv[0]);
return 1;
}
}
else if ((memcmp (option_name, "l2entry", option_len) == 0) &&
(option_len == strlen ("l2entry")))
{
if (getFlag && macFlag) /* Search a MAC entry */
{
get_l2Entry (&clientHandle, tenant, macAddr);
}
else if (getFlag) /* Get all MAC entries of a specified tenant */
{
get_l2Entries (&clientHandle, tenant);
}
else if (addFlag && macFlag && (tunnelHandle || accessIntfNum))
{
if ((tenant == 0) || (memcmp (macAddr, nullMac, sizeof (nullMac)) == 0))
{
printUsage (argv[0]);
return 1;
}
if (tunnelHandle)
{
l2DestIntf = tunnelHandle;
}
else
{
l2DestIntf = accessIntfNum;
}
add_l2Entry (&clientHandle, tenant, macAddr, l2DestIntf);
}
else if (!addFlag && macFlag && tenant)
{
if (memcmp (macAddr, nullMac, sizeof (nullMac)) == 0)
{
printUsage (argv[0]);
return 1;
}
del_l2Entry (&clientHandle, tenant, macAddr);
}
else
{
printUsage (argv[0]);
return 1;
}
}
else if ((memcmp (option_name, "tenant", option_len) == 0) && (option_len == strlen ("tenant")))
{
if (getFlag)
{
get_tenant (&clientHandle, tenant);
}
else if (addFlag)
{
create_tenant (&clientHandle, tenant, tunnel_type, vlanId, srcIP, configFlags);
}
else
{
delete_tenant (&clientHandle, tenant);
}
}
else if ((memcmp (option_name, "access", option_len) == 0) && (option_len == strlen ("access")))
{
if (getFlag && accessIntfNum)
{
get_access_port (&clientHandle, accessIntfNum);
}
else if (getFlag)
{
get_access_ports (&clientHandle, tenant);
}
else
{
printUsage (argv[0]);
return 1;
}
}
else if ((memcmp (option_name, "tunnel", option_len) == 0) && (option_len == strlen ("tunnel")))
{
if (getFlag)
{
if (tunnelHandle)
{
get_tunnel_status (&clientHandle, tunnelHandle);
}
else /* list down all tunnels */
{
get_all_tunnels (&clientHandle);
}
}
else if (addFlag)
{
create_tunnel (&clientHandle, tenant, remoteIP, configFlags, tunnelHandle);
}
else
{
delete_tunnel (&clientHandle, tunnelHandle);
}
}
else if ((memcmp (option_name, "stats", option_len) == 0) && (option_len == strlen ("stats")))
{
if ((getFlag) && (tunnelHandle))
{
tunnel_stats_get (&clientHandle, tunnelHandle);
}
else if ((!addFlag) && (tunnelHandle))
{
tunnel_stats_clear (&clientHandle, tunnelHandle);
}
else if (getFlag)
{
resource_stats_get (&clientHandle);
}
else
{
printf ("Incorrect options specified!\n");
printUsage (argv[0]);
}
}
else
{
printf ("Incorrect option specified %s \n", option_name);
printUsage (argv[0]);
}
/* Log goodbye message with OpEN */
L7PROC_LOGF(L7PROC_LOG_SEVERITY_INFO, 0, "Stopping Overlay API example application");
(void) openapiClientTearDown(&clientHandle);
return 0;
}