mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-04 09:45:13 +00:00 
			
		
		
		
	Signed-off-by: Brady Johnson <brady@voltanet.io> Co-authored-by: Javier Garcia <javier.garcia@voltanet.io> Signed-off-by: Javier Garcia <javier.garcia@voltanet.io>
		
			
				
	
	
		
			476 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			476 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * This file is part of the PCEPlib, a PCEP protocol library.
 | 
						|
 *
 | 
						|
 * Copyright (C) 2020 Volta Networks https://voltanet.io/
 | 
						|
 *
 | 
						|
 * This library is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU Lesser General Public
 | 
						|
 * License as published by the Free Software Foundation; either
 | 
						|
 * version 2 of the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This library 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
 | 
						|
 * Lesser General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU Lesser General Public License
 | 
						|
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
						|
 *
 | 
						|
 * Author : Brady Johnson <brady@voltanet.io>
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Implementation of PCEP Counters.
 | 
						|
 */
 | 
						|
 | 
						|
#include <zebra.h>
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <time.h>
 | 
						|
 | 
						|
#include "pcep_utils_counters.h"
 | 
						|
#include "pcep_utils_logging.h"
 | 
						|
#include "pcep_utils_memory.h"
 | 
						|
 | 
						|
struct counters_group *create_counters_group(const char *group_name,
 | 
						|
					     uint16_t max_subgroups)
 | 
						|
{
 | 
						|
	if (group_name == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot create counters group: group_name is NULL.",
 | 
						|
			__func__);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	if (max_subgroups > MAX_COUNTER_GROUPS) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot create counters group: max_subgroups [%d] is larger than max the [%d].",
 | 
						|
			__func__, max_subgroups, MAX_COUNTER_GROUPS);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	struct counters_group *group =
 | 
						|
		pceplib_malloc(PCEPLIB_INFRA, sizeof(struct counters_group));
 | 
						|
	memset(group, 0, sizeof(struct counters_group));
 | 
						|
	group->subgroups =
 | 
						|
		pceplib_malloc(PCEPLIB_INFRA, sizeof(struct counters_subgroup *)
 | 
						|
						      * (max_subgroups + 1));
 | 
						|
	memset(group->subgroups, 0,
 | 
						|
	       sizeof(struct counters_subgroup *) * (max_subgroups + 1));
 | 
						|
 | 
						|
	strlcpy(group->counters_group_name, group_name,
 | 
						|
		sizeof(group->counters_group_name));
 | 
						|
	group->max_subgroups = max_subgroups;
 | 
						|
	group->start_time = time(NULL);
 | 
						|
 | 
						|
	return group;
 | 
						|
}
 | 
						|
 | 
						|
struct counters_subgroup *create_counters_subgroup(const char *subgroup_name,
 | 
						|
						   uint16_t subgroup_id,
 | 
						|
						   uint16_t max_counters)
 | 
						|
{
 | 
						|
	if (subgroup_name == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot create counters subgroup: subgroup_name is NULL.",
 | 
						|
			__func__);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	if (max_counters > MAX_COUNTERS) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot create counters subgroup: max_counters [%d] is larger than the max [%d].",
 | 
						|
			__func__, max_counters, MAX_COUNTERS);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	if (subgroup_id > MAX_COUNTER_GROUPS) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot create counters subgroup: subgroup_id [%d] is larger than max the [%d].",
 | 
						|
			__func__, subgroup_id, MAX_COUNTER_GROUPS);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	struct counters_subgroup *subgroup =
 | 
						|
		pceplib_malloc(PCEPLIB_INFRA, sizeof(struct counters_subgroup));
 | 
						|
	memset(subgroup, 0, sizeof(struct counters_subgroup));
 | 
						|
	subgroup->counters = pceplib_malloc(
 | 
						|
		PCEPLIB_INFRA, sizeof(struct counter *) * (max_counters + 1));
 | 
						|
	memset(subgroup->counters, 0,
 | 
						|
	       sizeof(struct counter *) * (max_counters + 1));
 | 
						|
 | 
						|
	strlcpy(subgroup->counters_subgroup_name, subgroup_name,
 | 
						|
		sizeof(subgroup->counters_subgroup_name));
 | 
						|
	subgroup->subgroup_id = subgroup_id;
 | 
						|
	subgroup->max_counters = max_counters;
 | 
						|
 | 
						|
	return subgroup;
 | 
						|
}
 | 
						|
 | 
						|
struct counters_subgroup *
 | 
						|
clone_counters_subgroup(struct counters_subgroup *subgroup,
 | 
						|
			const char *subgroup_name, uint16_t subgroup_id)
 | 
						|
{
 | 
						|
	if (subgroup == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot clone counters subgroup: input counters_subgroup is NULL.",
 | 
						|
			__func__);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	if (subgroup_name == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot clone counters subgroup: subgroup_name is NULL.",
 | 
						|
			__func__);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	if (subgroup_id > MAX_COUNTER_GROUPS) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot clone counters subgroup: subgroup_id [%d] is larger than max the [%d].",
 | 
						|
			__func__, subgroup_id, MAX_COUNTER_GROUPS);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	struct counters_subgroup *cloned_subgroup = create_counters_subgroup(
 | 
						|
		subgroup_name, subgroup_id, subgroup->max_counters);
 | 
						|
	int i = 0;
 | 
						|
	for (; i <= subgroup->max_counters; i++) {
 | 
						|
		struct counter *counter = subgroup->counters[i];
 | 
						|
		if (counter != NULL) {
 | 
						|
			create_subgroup_counter(cloned_subgroup,
 | 
						|
						counter->counter_id,
 | 
						|
						counter->counter_name);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return cloned_subgroup;
 | 
						|
}
 | 
						|
 | 
						|
bool add_counters_subgroup(struct counters_group *group,
 | 
						|
			   struct counters_subgroup *subgroup)
 | 
						|
{
 | 
						|
	if (group == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot add counters subgroup: counters_group is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	if (subgroup == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot add counters subgroup: counters_subgroup is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	if (subgroup->subgroup_id >= group->max_subgroups) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot add counters subgroup: counters_subgroup id [%d] is larger than the group max_subgroups [%d].",
 | 
						|
			__func__, subgroup->subgroup_id, group->max_subgroups);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	group->num_subgroups++;
 | 
						|
	group->subgroups[subgroup->subgroup_id] = subgroup;
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool create_subgroup_counter(struct counters_subgroup *subgroup,
 | 
						|
			     uint32_t counter_id, const char *counter_name)
 | 
						|
{
 | 
						|
	if (subgroup == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot create subgroup counter: counters_subgroup is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	if (counter_id >= subgroup->max_counters) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot create subgroup counter: counter_id [%d] is larger than the subgroup max_counters [%d].",
 | 
						|
			__func__, counter_id, subgroup->max_counters);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	if (counter_name == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot create subgroup counter: counter_name is NULL.",
 | 
						|
			__func__);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	struct counter *counter =
 | 
						|
		pceplib_malloc(PCEPLIB_INFRA, sizeof(struct counter));
 | 
						|
	memset(counter, 0, sizeof(struct counter));
 | 
						|
	counter->counter_id = counter_id;
 | 
						|
	strlcpy(counter->counter_name, counter_name,
 | 
						|
		sizeof(counter->counter_name));
 | 
						|
 | 
						|
	subgroup->num_counters++;
 | 
						|
	subgroup->counters[counter->counter_id] = counter;
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool delete_counters_group(struct counters_group *group)
 | 
						|
{
 | 
						|
	if (group == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot delete group counters: counters_group is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	int i = 0;
 | 
						|
	for (; i <= group->max_subgroups; i++) {
 | 
						|
		struct counters_subgroup *subgroup = group->subgroups[i];
 | 
						|
		if (subgroup != NULL) {
 | 
						|
			delete_counters_subgroup(subgroup);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	pceplib_free(PCEPLIB_INFRA, group->subgroups);
 | 
						|
	pceplib_free(PCEPLIB_INFRA, group);
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool delete_counters_subgroup(struct counters_subgroup *subgroup)
 | 
						|
{
 | 
						|
	if (subgroup == NULL || subgroup->counters == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot delete subgroup counters: counters_subgroup is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	int i = 0;
 | 
						|
	for (; i <= subgroup->max_counters; i++) {
 | 
						|
		struct counter *counter = subgroup->counters[i];
 | 
						|
		if (counter != NULL) {
 | 
						|
			pceplib_free(PCEPLIB_INFRA, counter);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	pceplib_free(PCEPLIB_INFRA, subgroup->counters);
 | 
						|
	pceplib_free(PCEPLIB_INFRA, subgroup);
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool reset_group_counters(struct counters_group *group)
 | 
						|
{
 | 
						|
	if (group == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot reset group counters: counters_group is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	int i = 0;
 | 
						|
	for (; i <= group->max_subgroups; i++) {
 | 
						|
		struct counters_subgroup *subgroup = group->subgroups[i];
 | 
						|
		if (subgroup != NULL) {
 | 
						|
			reset_subgroup_counters(subgroup);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	group->start_time = time(NULL);
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool reset_subgroup_counters(struct counters_subgroup *subgroup)
 | 
						|
{
 | 
						|
	if (subgroup == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot reset subgroup counters: counters_subgroup is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	int i = 0;
 | 
						|
	for (; i <= subgroup->max_counters; i++) {
 | 
						|
		struct counter *counter = subgroup->counters[i];
 | 
						|
		if (counter != NULL) {
 | 
						|
			counter->counter_value = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool increment_counter(struct counters_group *group, uint16_t subgroup_id,
 | 
						|
		       uint16_t counter_id)
 | 
						|
{
 | 
						|
	if (group == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot increment counter: counters_group is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	if (subgroup_id >= group->max_subgroups) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_DEBUG,
 | 
						|
			"%s: Cannot increment counter: subgroup_id [%d] is larger than the group max_subgroups [%d].",
 | 
						|
			__func__, subgroup_id, group->max_subgroups);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	struct counters_subgroup *subgroup = group->subgroups[subgroup_id];
 | 
						|
	if (subgroup == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot increment counter: counters_subgroup in counters_group is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	return increment_subgroup_counter(subgroup, counter_id);
 | 
						|
}
 | 
						|
 | 
						|
bool increment_subgroup_counter(struct counters_subgroup *subgroup,
 | 
						|
				uint16_t counter_id)
 | 
						|
{
 | 
						|
	if (subgroup == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot increment counter: counters_subgroup is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	if (counter_id >= subgroup->max_counters) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_DEBUG,
 | 
						|
			"%s: Cannot increment counter: counter_id [%d] is larger than the subgroup max_counters [%d].",
 | 
						|
			__func__, counter_id, subgroup->max_counters);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	if (subgroup->counters[counter_id] == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot increment counter: No counter exists for counter_id [%d].",
 | 
						|
			__func__, counter_id);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	subgroup->counters[counter_id]->counter_value++;
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool dump_counters_group_to_log(struct counters_group *group)
 | 
						|
{
 | 
						|
	if (group == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot dump group counters to log: counters_group is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	time_t now = time(NULL);
 | 
						|
	pcep_log(
 | 
						|
		LOG_INFO,
 | 
						|
		"%s: PCEP Counters group:\n  %s \n  Sub-Groups [%d] \n  Active for [%d seconds]",
 | 
						|
		__func__, group->counters_group_name, group->num_subgroups,
 | 
						|
		(now - group->start_time));
 | 
						|
 | 
						|
	int i = 0;
 | 
						|
	for (; i <= group->max_subgroups; i++) {
 | 
						|
		struct counters_subgroup *subgroup = group->subgroups[i];
 | 
						|
		if (subgroup != NULL) {
 | 
						|
			dump_counters_subgroup_to_log(subgroup);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool dump_counters_subgroup_to_log(struct counters_subgroup *subgroup)
 | 
						|
{
 | 
						|
	if (subgroup == NULL) {
 | 
						|
		pcep_log(
 | 
						|
			LOG_INFO,
 | 
						|
			"%s: Cannot dump subgroup counters to log: counters_subgroup is NULL.",
 | 
						|
			__func__);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	pcep_log(LOG_INFO,
 | 
						|
		 "%s: \tPCEP Counters sub-group [%s] with [%d] counters",
 | 
						|
		 __func__, subgroup->counters_subgroup_name,
 | 
						|
		 subgroup->num_counters);
 | 
						|
 | 
						|
	int i = 0;
 | 
						|
	for (; i <= subgroup->max_counters; i++) {
 | 
						|
		struct counter *counter = subgroup->counters[i];
 | 
						|
		if (counter != NULL) {
 | 
						|
			pcep_log(LOG_INFO, "%s: \t\t%s %d", __func__,
 | 
						|
				 counter->counter_name, counter->counter_value);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
struct counters_subgroup *find_subgroup(const struct counters_group *group,
 | 
						|
					uint16_t subgroup_id)
 | 
						|
{
 | 
						|
	int i = 0;
 | 
						|
	for (; i <= group->max_subgroups; i++) {
 | 
						|
		struct counters_subgroup *subgroup = group->subgroups[i];
 | 
						|
		if (subgroup != NULL) {
 | 
						|
			if (subgroup->subgroup_id == subgroup_id) {
 | 
						|
				return subgroup;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t subgroup_counters_total(struct counters_subgroup *subgroup)
 | 
						|
{
 | 
						|
	if (subgroup == NULL) {
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	uint32_t counter_total = 0;
 | 
						|
	int i = 0;
 | 
						|
	for (; i <= subgroup->max_counters; i++) {
 | 
						|
		struct counter *counter = subgroup->counters[i];
 | 
						|
		if (counter != NULL) {
 | 
						|
			counter_total += counter->counter_value;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return counter_total;
 | 
						|
}
 |