Open Ethernet Networking (OpEN) API Guide and Reference Manual  3.6.0.3
bfd_monitor.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 bfd_monitor.c
*
* @purpose Monitor BFD Sessions.
*
* @component OPEN
*
* @note
* This program interfaces directly with the syncdb database to
* monitor the BFD session state.
* If the NOS is not running when this program is started then the
* program exits.
* If the NOS stops while the program is running then the program
* exits.
*
* @create 09/08/2015
*
* @end
*
**********************************************************************/
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_packet.h>
#include <sys/errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "rpcclt_openapi.h"
#include "proc_util.h"
#include "openapi_common.h"
#include "openapi_syncdb.h"
/*****************************************************************/
void syncdbBfdMonitorClientRegister(void)
{
int rc;
rc = syncdbClientRegister ("BFD Monitor", &client_id);
if (rc != SYNCDB_OK)
{
exit (1);
}
rc = syncdbTableChangeNotify (&client_id, SYNCDB_OPENAPI_BFD);
if (rc != SYNCDB_OK)
{
exit (1);
}
}
/*****************************************************************/
const char *ipAddressFormat(open_inet_addr_t *addr, char *buffer)
{
uint32_t ip4_addr;
uint8_t addr8[16];
int af;
switch (addr->family)
{
af = AF_INET;
ip4_addr = htonl(addr->addr.ipv4);
memcpy(addr8, &ip4_addr, sizeof(ip4_addr));
break;
af = AF_INET6;
memcpy(addr8, addr->addr.ipv6.u.addr8, sizeof(addr8));
break;
default:
return(NULL);
}
return(inet_ntop(af, addr8, buffer, INET6_ADDRSTRLEN));
}
/*****************************************************************/
void routerBfdEventLog (openBfdSessionInfo_t *bfd_info, int delete_pending)
{
char src_ip[256];
char dst_ip[256];
char next_hop[256];
const char *rc1, *rc2, *rc3;
if (delete_pending == 0)
{
printf("Event Type: Add/Change\n");
} else
{
printf("Event Type: Delete\n");
}
rc1 = ipAddressFormat (&bfd_info->key.srcIpAddr, src_ip);
if (rc1 == 0)
{
sprintf (src_ip, "None");
}
rc2 = ipAddressFormat (&bfd_info->key.dstIpAddr, dst_ip);
if (rc2 == 0)
{
sprintf (dst_ip, "None");
}
rc3 = ipAddressFormat (&bfd_info->nextHopIpAddr, next_hop);
if (rc3 == 0)
{
sprintf (next_hop, "None");
}
printf ("Session State:%d\n", bfd_info->state);
printf ("Diag Code:%d\n", bfd_info->diag);
printf ("Session ID:%d\n", bfd_info->session_id);
printf ("SA Family:%d\n", bfd_info->key.srcIpAddr.family);
printf ("Source IP Address:%s\n", src_ip);
printf ("Destination IP Address:%s\n", dst_ip);
printf ("Next Hop IP Address:%s\n", next_hop);
printf ("MPLS Label Stack:%d %d %d\n",
bfd_info->key.mpls_label.label[0],
bfd_info->key.mpls_label.label[1],
bfd_info->key.mpls_label.label[2]);
printf ("\n");
}
/*****************************************************************/
void bfdEventHandle (void)
{
int rc;
openBfdSessionInfo_t bfd_info = {};
int delete_pending;
/* The NOS may already have BFD connections, so read the database before
** starting to wait for table-changed notifications.
*/
do
{
rc = syncdbGetNext(&client_id, SYNCDB_OPENAPI_BFD,
&bfd_info, sizeof (bfd_info),
&delete_pending);
if (rc == SYNCDB_ERROR)
{
exit (1);
}
if (rc == SYNCDB_OK)
{
routerBfdEventLog(&bfd_info, delete_pending);
}
} while (rc == SYNCDB_OK);
do
{
/* Wait two seconds for table notification event.
** The reason we are waiting with a timeout is to detect if the NOS
** stops running.
*/
(void) syncdbTableChangeCheck (&client_id, 2);
memset (&bfd_info, 0, sizeof (bfd_info));
do
{
rc = syncdbGetNextChanged (&client_id, SYNCDB_OPENAPI_BFD,
&bfd_info, sizeof (bfd_info),
&delete_pending);
if (rc == SYNCDB_ERROR)
{
exit (1);
}
if (rc == SYNCDB_OK)
{
routerBfdEventLog(&bfd_info, delete_pending);
}
} while (rc == SYNCDB_OK);
} while (1);
}
int main(int argc, char **argv)
{
int pid, status;
do
{
pid = fork ();
if (pid == 0)
{
syncdbBfdMonitorClientRegister ();
bfdEventHandle ();
} else
{
do
{
pid = waitpid (pid, &status, 0);
} while ((-1 == pid) && (EINTR == errno));
}
printf ("The NOS is not running. Retry in 1 second...\n");
sleep (1);
} while (1);
return 0;
}