Open Ethernet Networking (OpEN) API Guide and Reference Manual  3.6.0.3
link_status_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 link_status_example.c
*
* @purpose Link Status Example.
*
* @component OPEN
*
* @note
*
* @create 09/04/2012
*
* @end
*
**********************************************************************/
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include "rpcclt_openapi.h"
#include "proc_util.h"
#include "openapi_common.h"
typedef struct
{
uint32_t interface_exists; /* This interface is know to the switch */
OPEN_LINK_STATE_t interface_link_status;
char name [256];
} interface_entry_t;
/* Local copy of the interface table.
*/
interface_entry_t *interface_table;
/* Print the list of all interfaces whose link status is UP.
** The information is obtained from the local database.
*/
void link_up_interface_show (uint32_t max_interfaces)
{
uint32_t i;
printf ("\n\nThe following interfaces are Link-UP\n");
for (i = 0; i < max_interfaces; i++)
{
if (!interface_table[i].interface_exists)
{
continue;
}
if (interface_table[i].interface_link_status != OPEN_LINK_UP)
{
continue;
}
printf ("ifindex:%d - Name:%s - Link Up.\n", i, interface_table[i].name);
}
}
/* Pupulate the local interface table when this application starts running.
*/
void interface_table_create (openapiClientHandle_t *client, uint32_t max_interfaces)
{
openapiEventList_t open_event;
uint32_t intf_num;
open_buffdesc linkNameBuff;
interface_table = malloc(sizeof(interface_entry_t) * max_interfaces);
printf ("Created Interface Table for %d interfaces.\n", max_interfaces);
/* Register with FASTPATH to receive interface-change events.
** The registration must be done before populating the interface table
** in order not to miss any interface change events.
*/
openapiEventListClear (&open_event);
openapiEventSet (&open_event, OPEN_EVENT_INTERFACE);
if (OPEN_E_NONE != openapiEventRegister(client, &open_event))
{
printf ("Failed to register for OPEN_EVENT_INTERFACE event.\n");
abort ();
}
/* Populate the interface table to match the current interface state.
*/
/* Interface 0 does not exist, so we won't miss any interfaces by calling NextGet on interface 0.
*/
intf_num = 0;
while (OPEN_E_NONE == openapiIfNextGet (client, OPEN_INTF_TYPE_ANY, intf_num, &intf_num))
{
interface_table[intf_num].interface_exists = 1;
if (OPEN_E_NONE != openapiIfLinkStateGet(client, intf_num,
&interface_table[intf_num].interface_link_status))
{
interface_table[intf_num].interface_exists = 0;
}
linkNameBuff.pstart = interface_table[intf_num].name;
linkNameBuff.size = sizeof(interface_table[intf_num].name);
if (OPEN_E_NONE != openapiIfNameGet(client, intf_num, &linkNameBuff))
{
interface_table[intf_num].interface_exists = 0;
}
}
link_up_interface_show (max_interfaces);
}
/* Check whether information about interfaces is still accurate.
*/
void interface_table_validate (openapiClientHandle_t *client,
uint32_t max_interfaces)
{
int i;
open_buffdesc linkNameBuff;
for (i = 0; i < max_interfaces; i++)
{
if (!interface_table[i].interface_exists)
{
continue;
}
/* Re-Populate the interface record. The interface could have gone away and
** come back with different name and link status.
*/
&interface_table[i].interface_link_status))
{
interface_table[i].interface_exists = 0;
}
linkNameBuff.pstart = interface_table[i].name;
linkNameBuff.size = sizeof(interface_table[i].name);
if (OPEN_E_NONE != openapiIfNameGet(client, i, &linkNameBuff))
{
interface_table[i].interface_exists = 0;
}
}
}
/* Wait for interface events for specified duration.
*/
void interface_table_monitor (openapiClientHandle_t *client,
uint32_t max_interfaces,
uint32_t monitor_duration)
{
struct timespec start_time, current_time;
openapiEventList_t change_pending_event, purge_event;
uint32_t intf_num, delete_pending;
open_buffdesc linkNameBuff;
if (clock_gettime (CLOCK_MONOTONIC, &start_time))
{
perror ("Can't get start time.\n");
abort ();
}
do
{
/* Wait for events. Time out every 5 seconds.
*/
if (OPEN_E_NONE == openapiEventWait (client, 5))
{
if (OPEN_E_NONE == openapiPendingEventsGet(client, &change_pending_event, &purge_event))
{
/* Sometimes FASTPATH deletes entries from the table without
** telling the application. This can happen if the table gets full
** before the application has a chance to acknowledge
** the delete-pending events.
** If an applicaton gets a purge notification then it must
** check all of its entries to see if they are still valid.
*/
if (openapiEventIsSet (&purge_event, OPEN_EVENT_INTERFACE))
{
printf ("Got Purge event for OPEN_EVENT_INTERFACE\n");
interface_table_validate (client, max_interfaces);
}
/* Debug code to confirm that we got an interface table event.
*/
if (openapiEventIsSet (&change_pending_event, OPEN_EVENT_INTERFACE))
{
printf ("Got Change Pending event for OPEN_EVENT_INTERFACE\n");
}
}
/* Walk through the changed entries in the interface table and
** update the local database.
*/
intf_num = 0;
while (OPEN_E_NONE == openapiIfNextChangedGet (client, intf_num, &intf_num, &delete_pending))
{
if (delete_pending)
{
/* Interface is pending for deletion. Remove it from the local database.
*/
printf ("Deleting ifindex:%d - Name:%s\n",
intf_num, interface_table[intf_num].name);
interface_table[intf_num].interface_exists = 0;
}
else
{
if (OPEN_E_NONE != openapiIfLinkStateGet(client, intf_num,
&interface_table[intf_num].interface_link_status))
{
interface_table[intf_num].interface_exists = 0;
}
else
{
printf ("ifindex:%d - Name:%s - Link %s.\n",
intf_num, interface_table[intf_num].name,
(interface_table[intf_num].interface_link_status == OPEN_LINK_UP)?"UP":"DOWN");
/* This may be a new interface. If so, then mark the interface as valid
** and fetch the interface name.
*/
if (!interface_table[intf_num].interface_exists)
{
interface_table[intf_num].interface_exists = 1;
linkNameBuff.pstart = interface_table[intf_num].name;
linkNameBuff.size = sizeof(interface_table[intf_num].name);
if (OPEN_E_NONE != openapiIfNameGet(client, intf_num, &linkNameBuff))
{
interface_table[intf_num].interface_exists = 0;
}
}
}
}
}
}
if (clock_gettime (CLOCK_MONOTONIC, &current_time))
{
perror ("Can't get current time.\n");
abort ();
}
} while ((current_time.tv_sec - start_time.tv_sec) < monitor_duration);
}
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 monitor_duration = 60;
uint32_t max_interfaces;
if ((argc != 1) && (argc != 2))
{
printf("Usage: %s [monitor-duration-seconds]\n", argv[0]);
exit(1);
}
if (argc == 2)
{
monitor_duration = atoi(argv[1]);
}
printf ("Monitoring Link Status for %d seconds.\n", monitor_duration);
l7proc_crashlog_register();
/* Register with OpEN */
if ((result = openapiClientRegister("link_status_example", &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 Link Status Monitor example application");
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");
printf("\n");
/* Log goodbye message with OPEN */
L7PROC_LOGF(L7PROC_LOG_SEVERITY_INFO, 0, "Stopping Link Status example application");
/* Determine the maximum number of interfaces supported on this switch.
*/
if (OPEN_E_NONE != openapiMaxInterfaceCountGet(&clientHandle, &max_interfaces))
{
printf ("Can't get Interface Count.\n");
return 0;
}
interface_table_create (&clientHandle, max_interfaces);
interface_table_monitor (&clientHandle, max_interfaces, monitor_duration);
link_up_interface_show (max_interfaces);
(void) openapiClientTearDown(&clientHandle);
return 0;
}