mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-04 15:04:05 +00:00 
			
		
		
		
	Before: ``` segment-routing traffic-eng mpls-te on mpls-te import ospfv2 ``` After: ``` segment-routing traffic-eng mpls-te on mpls-te import ospfv2 ``` Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
		
			
				
	
	
		
			727 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			727 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (C) 2020 Volta Networks, 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 Lesser General Public License
 | 
						|
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
						|
 */
 | 
						|
 | 
						|
#include "stdlib.h"
 | 
						|
 | 
						|
#include <zebra.h>
 | 
						|
 | 
						|
#include "memory.h"
 | 
						|
#include "log.h"
 | 
						|
#include "command.h"
 | 
						|
#include "prefix.h"
 | 
						|
#include <lib/json.h>
 | 
						|
 | 
						|
#include "pathd.h"
 | 
						|
#include "pathd/path_errors.h"
 | 
						|
#include "pathd/path_ted.h"
 | 
						|
 | 
						|
#ifndef VTYSH_EXTRACT_PL
 | 
						|
#include "pathd/path_ted_clippy.c"
 | 
						|
#endif
 | 
						|
 | 
						|
static struct ls_ted *path_ted_create_ted(void);
 | 
						|
static void path_ted_register_vty(void);
 | 
						|
static void path_ted_unregister_vty(void);
 | 
						|
static uint32_t path_ted_start_importing_igp(const char *daemon_str);
 | 
						|
static uint32_t path_ted_stop_importing_igp(void);
 | 
						|
static enum zclient_send_status path_ted_link_state_sync(void);
 | 
						|
static int path_ted_timer_handler_sync(struct thread *thread);
 | 
						|
static int path_ted_timer_handler_refresh(struct thread *thread);
 | 
						|
static int path_ted_cli_debug_config_write(struct vty *vty);
 | 
						|
static int path_ted_cli_debug_set_all(uint32_t flags, bool set);
 | 
						|
 | 
						|
extern struct zclient *zclient;
 | 
						|
 | 
						|
struct ted_state ted_state_g = {};
 | 
						|
 | 
						|
/*
 | 
						|
 * path_path_ted public API function implementations
 | 
						|
 */
 | 
						|
 | 
						|
void path_ted_init(struct thread_master *master)
 | 
						|
{
 | 
						|
	ted_state_g.main = master;
 | 
						|
	ted_state_g.link_state_delay_interval = TIMER_RETRY_DELAY;
 | 
						|
	ted_state_g.segment_list_refresh_interval = TIMER_RETRY_DELAY;
 | 
						|
	path_ted_register_vty();
 | 
						|
	path_ted_segment_list_refresh();
 | 
						|
}
 | 
						|
 | 
						|
uint32_t path_ted_teardown(void)
 | 
						|
{
 | 
						|
	PATH_TED_DEBUG("%s : TED [%p]", __func__, ted_state_g.ted);
 | 
						|
	path_ted_unregister_vty();
 | 
						|
	path_ted_stop_importing_igp();
 | 
						|
	ls_ted_del_all(ted_state_g.ted);
 | 
						|
	path_ted_timer_sync_cancel();
 | 
						|
	path_ted_timer_refresh_cancel();
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Set all needed to receive igp data.
 | 
						|
 *
 | 
						|
 * @return		true if ok
 | 
						|
 *
 | 
						|
 */
 | 
						|
uint32_t path_ted_start_importing_igp(const char *daemon_str)
 | 
						|
{
 | 
						|
	uint32_t status = 0;
 | 
						|
 | 
						|
	if (strcmp(daemon_str, "ospfv2") == 0)
 | 
						|
		ted_state_g.import = IMPORT_OSPFv2;
 | 
						|
	else if (strcmp(daemon_str, "ospfv3") == 0) {
 | 
						|
		ted_state_g.import = IMPORT_UNKNOWN;
 | 
						|
		return 1;
 | 
						|
	} else if (strcmp(daemon_str, "isis") == 0)
 | 
						|
		ted_state_g.import = IMPORT_ISIS;
 | 
						|
	else {
 | 
						|
		ted_state_g.import = IMPORT_UNKNOWN;
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
 | 
						|
	if (ls_register(zclient, false /*client*/) != 0) {
 | 
						|
		PATH_TED_ERROR("%s: PATHD-TED: Unable to register Link State",
 | 
						|
			       __func__);
 | 
						|
		ted_state_g.import = IMPORT_UNKNOWN;
 | 
						|
		status = 1;
 | 
						|
	} else {
 | 
						|
		if (path_ted_link_state_sync() != -1) {
 | 
						|
			PATH_TED_DEBUG("%s: PATHD-TED: Importing %s data ON",
 | 
						|
				       __func__,
 | 
						|
				       PATH_TED_IGP_PRINT(ted_state_g.import));
 | 
						|
		} else {
 | 
						|
			PATH_TED_WARN("%s: PATHD-TED: Importing %s data OFF",
 | 
						|
				      __func__,
 | 
						|
				      PATH_TED_IGP_PRINT(ted_state_g.import));
 | 
						|
			ted_state_g.import = IMPORT_UNKNOWN;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Unset all needed to receive igp data.
 | 
						|
 *
 | 
						|
 * @return		true if ok
 | 
						|
 *
 | 
						|
 */
 | 
						|
uint32_t path_ted_stop_importing_igp(void)
 | 
						|
{
 | 
						|
	uint32_t status = 0;
 | 
						|
 | 
						|
	if (ted_state_g.import != IMPORT_UNKNOWN) {
 | 
						|
		if (ls_unregister(zclient, false /*client*/) != 0) {
 | 
						|
			PATH_TED_ERROR(
 | 
						|
				"%s: PATHD-TED: Unable to unregister Link State",
 | 
						|
				__func__);
 | 
						|
			status = 1;
 | 
						|
		} else {
 | 
						|
			ted_state_g.import = IMPORT_UNKNOWN;
 | 
						|
			PATH_TED_DEBUG("%s: PATHD-TED: Importing igp data OFF",
 | 
						|
				   __func__);
 | 
						|
		}
 | 
						|
		path_ted_timer_sync_cancel();
 | 
						|
	}
 | 
						|
	return status;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * Check for ted status
 | 
						|
 *
 | 
						|
 * @return		true if ok
 | 
						|
 *
 | 
						|
 */
 | 
						|
bool path_ted_is_initialized(void)
 | 
						|
{
 | 
						|
	if (ted_state_g.ted == NULL) {
 | 
						|
		PATH_TED_WARN("PATHD TED ls_ted not initialized");
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Creates an empty ted
 | 
						|
 *
 | 
						|
 * @param void
 | 
						|
 *
 | 
						|
 * @return		Ptr to ted or NULL
 | 
						|
 */
 | 
						|
struct ls_ted *path_ted_create_ted()
 | 
						|
{
 | 
						|
	struct ls_ted *ted = ls_ted_new(TED_KEY, TED_NAME, TED_ASN);
 | 
						|
 | 
						|
	if (ted == NULL) {
 | 
						|
		PATH_TED_ERROR("%s Unable to initialize TED Key [%d] ASN [%d] Name [%s]",
 | 
						|
			 __func__, TED_KEY, TED_ASN, TED_NAME);
 | 
						|
	} else {
 | 
						|
		PATH_TED_INFO("%s Initialize TED Key [%d] ASN [%d] Name [%s]",
 | 
						|
			 __func__, TED_KEY, TED_ASN, TED_NAME);
 | 
						|
	}
 | 
						|
 | 
						|
	return ted;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t path_ted_rcvd_message(struct ls_message *msg)
 | 
						|
{
 | 
						|
	if (!path_ted_is_initialized())
 | 
						|
		return 1;
 | 
						|
 | 
						|
	if (msg == NULL) {
 | 
						|
		PATH_TED_ERROR("%s: [rcv ted] TED received NULL message ",
 | 
						|
			       __func__);
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
 | 
						|
	if (path_ted_get_current_igp(msg->data.node->adv.origin))
 | 
						|
		return 1;
 | 
						|
 | 
						|
	switch (msg->type) {
 | 
						|
	case LS_MSG_TYPE_NODE:
 | 
						|
		ls_msg2vertex(ted_state_g.ted, msg, true /*hard delete*/);
 | 
						|
		break;
 | 
						|
 | 
						|
	case LS_MSG_TYPE_ATTRIBUTES:
 | 
						|
		ls_msg2edge(ted_state_g.ted, msg, true /*ĥard delete*/);
 | 
						|
		break;
 | 
						|
 | 
						|
	case LS_MSG_TYPE_PREFIX:
 | 
						|
		ls_msg2subnet(ted_state_g.ted, msg, true /*hard delete*/);
 | 
						|
		break;
 | 
						|
 | 
						|
	default:
 | 
						|
		PATH_TED_DEBUG(
 | 
						|
			"%s: [rcv ted] TED received unknown message type [%d]",
 | 
						|
			__func__, msg->type);
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t path_ted_query_type_f(struct ipaddr *local, struct ipaddr *remote)
 | 
						|
{
 | 
						|
	uint32_t sid = MPLS_LABEL_NONE;
 | 
						|
	struct ls_edge *edge;
 | 
						|
	uint64_t key;
 | 
						|
 | 
						|
	if (!path_ted_is_initialized())
 | 
						|
		return MPLS_LABEL_NONE;
 | 
						|
 | 
						|
	if (!local || !remote)
 | 
						|
		return MPLS_LABEL_NONE;
 | 
						|
 | 
						|
	switch (local->ipa_type) {
 | 
						|
	case IPADDR_V4:
 | 
						|
		/* We have local and remote ip */
 | 
						|
		/* so check all attributes in ted */
 | 
						|
		key = ((uint64_t)ntohl(local->ip._v4_addr.s_addr)) & 0xffffffff;
 | 
						|
		edge = ls_find_edge_by_key(ted_state_g.ted, key);
 | 
						|
		if (edge) {
 | 
						|
			if (edge->attributes->standard.remote.s_addr
 | 
						|
				    == remote->ip._v4_addr.s_addr
 | 
						|
			    && CHECK_FLAG(edge->attributes->flags,
 | 
						|
					  LS_ATTR_ADJ_SID)) {
 | 
						|
				sid = edge->attributes->adj_sid[0]
 | 
						|
					      .sid; /* from primary */
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case IPADDR_V6:
 | 
						|
		key = (uint64_t)(local->ip._v6_addr.s6_addr32[0] & 0xffffffff)
 | 
						|
		      | ((uint64_t)local->ip._v6_addr.s6_addr32[1] << 32);
 | 
						|
		edge = ls_find_edge_by_key(ted_state_g.ted, key);
 | 
						|
		if (edge) {
 | 
						|
			if ((memcmp(&edge->attributes->standard.remote6,
 | 
						|
				    &remote->ip._v6_addr,
 | 
						|
				    sizeof(remote->ip._v6_addr))
 | 
						|
			     && CHECK_FLAG(edge->attributes->flags,
 | 
						|
					   LS_ATTR_ADJ_SID))) {
 | 
						|
				sid = edge->attributes->adj_sid[0]
 | 
						|
					      .sid; /* from primary */
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case IPADDR_NONE:
 | 
						|
		break;
 | 
						|
	}
 | 
						|
 | 
						|
	return sid;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t path_ted_query_type_c(struct prefix *prefix, uint8_t algo)
 | 
						|
{
 | 
						|
	uint32_t sid = MPLS_LABEL_NONE;
 | 
						|
	struct ls_subnet *subnet;
 | 
						|
 | 
						|
	if (!path_ted_is_initialized())
 | 
						|
		return MPLS_LABEL_NONE;
 | 
						|
 | 
						|
	if (!prefix)
 | 
						|
		return MPLS_LABEL_NONE;
 | 
						|
 | 
						|
	switch (prefix->family) {
 | 
						|
	case AF_INET:
 | 
						|
	case AF_INET6:
 | 
						|
		subnet = ls_find_subnet(ted_state_g.ted, *prefix);
 | 
						|
		if (subnet) {
 | 
						|
			if ((CHECK_FLAG(subnet->ls_pref->flags, LS_PREF_SR))
 | 
						|
			    && (subnet->ls_pref->sr.algo == algo))
 | 
						|
				sid = subnet->ls_pref->sr.sid;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		break;
 | 
						|
	}
 | 
						|
 | 
						|
	return sid;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t path_ted_query_type_e(struct prefix *prefix, uint32_t iface_id)
 | 
						|
{
 | 
						|
	uint32_t sid = MPLS_LABEL_NONE;
 | 
						|
	struct ls_subnet *subnet;
 | 
						|
	struct listnode *lst_node;
 | 
						|
	struct ls_edge *edge;
 | 
						|
 | 
						|
	if (!path_ted_is_initialized())
 | 
						|
		return MPLS_LABEL_NONE;
 | 
						|
 | 
						|
	if (!prefix)
 | 
						|
		return MPLS_LABEL_NONE;
 | 
						|
 | 
						|
	switch (prefix->family) {
 | 
						|
	case AF_INET:
 | 
						|
	case AF_INET6:
 | 
						|
		subnet = ls_find_subnet(ted_state_g.ted, *prefix);
 | 
						|
		if (subnet && subnet->vertex
 | 
						|
		    && subnet->vertex->outgoing_edges) {
 | 
						|
			/* from the vertex linked in subnet */
 | 
						|
			/* loop over outgoing edges */
 | 
						|
			for (ALL_LIST_ELEMENTS_RO(
 | 
						|
				     subnet->vertex->outgoing_edges, lst_node,
 | 
						|
				     edge)) {
 | 
						|
				/* and look for ifaceid */
 | 
						|
				/* so get sid of attribute */
 | 
						|
				if (CHECK_FLAG(edge->attributes->flags,
 | 
						|
					       LS_ATTR_LOCAL_ID)
 | 
						|
				    && edge->attributes->standard.local_id
 | 
						|
					       == iface_id) {
 | 
						|
					sid = subnet->ls_pref->sr.sid;
 | 
						|
					break;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		break;
 | 
						|
	}
 | 
						|
 | 
						|
	return sid;
 | 
						|
}
 | 
						|
 | 
						|
DEFPY (debug_path_ted,
 | 
						|
       debug_path_ted_cmd,
 | 
						|
       "[no] debug pathd mpls-te",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       "path debugging\n"
 | 
						|
       "ted debugging\n")
 | 
						|
{
 | 
						|
	uint32_t mode = DEBUG_NODE2MODE(vty->node);
 | 
						|
	bool no_debug = (no != NULL);
 | 
						|
 | 
						|
	DEBUG_MODE_SET(&ted_state_g.dbg, mode, !no);
 | 
						|
	DEBUG_FLAGS_SET(&ted_state_g.dbg, PATH_TED_DEBUG_BASIC, !no_debug);
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Followings are vty command functions.
 | 
						|
 */
 | 
						|
/* clang-format off */
 | 
						|
DEFUN (path_ted_on,
 | 
						|
       path_ted_on_cmd,
 | 
						|
       "mpls-te on",
 | 
						|
       NO_STR
 | 
						|
       "Enable the TE database (TED) functionality\n")
 | 
						|
/* clang-format on */
 | 
						|
{
 | 
						|
 | 
						|
	if (ted_state_g.enabled) {
 | 
						|
		PATH_TED_DEBUG("%s: PATHD-TED: Enabled ON -> ON.", __func__);
 | 
						|
		return CMD_SUCCESS;
 | 
						|
	}
 | 
						|
 | 
						|
	ted_state_g.ted = path_ted_create_ted();
 | 
						|
	ted_state_g.enabled = true;
 | 
						|
	PATH_TED_DEBUG("%s: PATHD-TED: Enabled OFF -> ON.", __func__);
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* clang-format off */
 | 
						|
DEFUN (no_path_ted,
 | 
						|
       no_path_ted_cmd,
 | 
						|
       "no mpls-te [on]",
 | 
						|
       NO_STR
 | 
						|
       NO_STR
 | 
						|
       "Disable the TE Database functionality\n")
 | 
						|
/* clang-format on */
 | 
						|
{
 | 
						|
	if (ted_state_g.enabled) {
 | 
						|
		PATH_TED_DEBUG("%s: PATHD-TED: OFF -> OFF", __func__);
 | 
						|
		return CMD_SUCCESS;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Remove TED */
 | 
						|
	ls_ted_del_all(ted_state_g.ted);
 | 
						|
	ted_state_g.enabled = false;
 | 
						|
	PATH_TED_DEBUG("%s: PATHD-TED: ON -> OFF", __func__);
 | 
						|
	ted_state_g.import = IMPORT_UNKNOWN;
 | 
						|
	if (ls_unregister(zclient, false /*client*/) != 0) {
 | 
						|
		vty_out(vty, "Unable to unregister Link State\n");
 | 
						|
		return CMD_WARNING;
 | 
						|
	}
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* clang-format off */
 | 
						|
DEFPY(path_ted_import,
 | 
						|
       path_ted_import_cmd,
 | 
						|
       "mpls-te import <ospfv2|ospfv3|isis>$import_daemon",
 | 
						|
       "Enable the TE database (TED) fill with remote igp data\n"
 | 
						|
       "import\n"
 | 
						|
       "Origin ospfv2\n"
 | 
						|
       "Origin ospfv3\n"
 | 
						|
       "Origin isis\n")
 | 
						|
/* clang-format on */
 | 
						|
{
 | 
						|
 | 
						|
	if (ted_state_g.enabled)
 | 
						|
		if (path_ted_start_importing_igp(import_daemon)) {
 | 
						|
			vty_out(vty, "Unable to start importing\n");
 | 
						|
			return CMD_WARNING;
 | 
						|
		}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* clang-format off */
 | 
						|
DEFUN (no_path_ted_import,
 | 
						|
       no_path_ted_import_cmd,
 | 
						|
       "no mpls-te import",
 | 
						|
       NO_STR
 | 
						|
       NO_STR
 | 
						|
       "Disable the TE Database fill with remote igp data\n")
 | 
						|
/* clang-format on */
 | 
						|
{
 | 
						|
 | 
						|
	if (ted_state_g.import) {
 | 
						|
		if (path_ted_stop_importing_igp()) {
 | 
						|
			vty_out(vty, "Unable to stop importing\n");
 | 
						|
			return CMD_WARNING;
 | 
						|
		} else {
 | 
						|
			PATH_TED_DEBUG(
 | 
						|
				"%s: PATHD-TED: Importing igp data already OFF",
 | 
						|
				__func__);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* clang-format off */
 | 
						|
DEFPY (show_pahtd_ted_db,
 | 
						|
       show_pathd_ted_db_cmd,
 | 
						|
       "show pathd ted database <verbose|json>$ver_json ",
 | 
						|
       "show command\n"
 | 
						|
       "pathd daemon\n"
 | 
						|
       "traffic eng\n"
 | 
						|
       "database\n"
 | 
						|
       "verbose output\n"
 | 
						|
       "Show complete received TED database\n")
 | 
						|
/* clang-format on */
 | 
						|
{
 | 
						|
	bool st_json = false;
 | 
						|
	json_object *json = NULL;
 | 
						|
 | 
						|
	if (!ted_state_g.enabled) {
 | 
						|
		vty_out(vty, "PATHD TED database is not enabled\n");
 | 
						|
		return CMD_WARNING;
 | 
						|
	}
 | 
						|
	if (strcmp(ver_json, "json") == 0) {
 | 
						|
		st_json = true;
 | 
						|
		json = json_object_new_object();
 | 
						|
	}
 | 
						|
	/* Show the complete TED */
 | 
						|
	ls_show_ted(ted_state_g.ted, vty, json, !st_json);
 | 
						|
	if (st_json) {
 | 
						|
		vty_out(vty, "%s\n",
 | 
						|
			json_object_to_json_string_ext(
 | 
						|
				json, JSON_C_TO_STRING_PRETTY));
 | 
						|
		json_object_free(json);
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Config Write functions
 | 
						|
 */
 | 
						|
 | 
						|
int path_ted_cli_debug_config_write(struct vty *vty)
 | 
						|
{
 | 
						|
	if (DEBUG_MODE_CHECK(&ted_state_g.dbg, DEBUG_MODE_CONF)) {
 | 
						|
		if (DEBUG_FLAGS_CHECK(&ted_state_g.dbg, PATH_TED_DEBUG_BASIC))
 | 
						|
			vty_out(vty, "debug pathd mpls-te\n");
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int path_ted_cli_debug_set_all(uint32_t flags, bool set)
 | 
						|
{
 | 
						|
	DEBUG_FLAGS_SET(&ted_state_g.dbg, flags, set);
 | 
						|
 | 
						|
	/* If all modes have been turned off, don't preserve options. */
 | 
						|
	if (!DEBUG_MODE_CHECK(&ted_state_g.dbg, DEBUG_MODE_ALL))
 | 
						|
		DEBUG_CLEAR(&ted_state_g.dbg);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Help fn to show ted related configuration
 | 
						|
 *
 | 
						|
 * @param vty
 | 
						|
 *
 | 
						|
 * @return		Status
 | 
						|
 */
 | 
						|
uint32_t path_ted_config_write(struct vty *vty)
 | 
						|
{
 | 
						|
 | 
						|
	if (ted_state_g.enabled) {
 | 
						|
		vty_out(vty, "  mpls-te on\n");
 | 
						|
		switch (ted_state_g.import) {
 | 
						|
		case IMPORT_ISIS:
 | 
						|
			vty_out(vty, "  mpls-te import isis\n");
 | 
						|
			break;
 | 
						|
		case IMPORT_OSPFv2:
 | 
						|
			vty_out(vty, "  mpls-te import ospfv2\n");
 | 
						|
			break;
 | 
						|
		case IMPORT_OSPFv3:
 | 
						|
			vty_out(vty, "  mpls-te import ospfv3\n");
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Register the fn's for CLI and hook for config show
 | 
						|
 *
 | 
						|
 * @param void
 | 
						|
 *
 | 
						|
 */
 | 
						|
static void path_ted_register_vty(void)
 | 
						|
{
 | 
						|
	install_element(VIEW_NODE, &show_pathd_ted_db_cmd);
 | 
						|
	install_element(SR_TRAFFIC_ENG_NODE, &path_ted_on_cmd);
 | 
						|
	install_element(SR_TRAFFIC_ENG_NODE, &no_path_ted_cmd);
 | 
						|
	install_element(SR_TRAFFIC_ENG_NODE, &path_ted_import_cmd);
 | 
						|
	install_element(SR_TRAFFIC_ENG_NODE, &no_path_ted_import_cmd);
 | 
						|
 | 
						|
	install_element(CONFIG_NODE, &debug_path_ted_cmd);
 | 
						|
	install_element(ENABLE_NODE, &debug_path_ted_cmd);
 | 
						|
 | 
						|
	hook_register(nb_client_debug_config_write,
 | 
						|
		      path_ted_cli_debug_config_write);
 | 
						|
	hook_register(nb_client_debug_set_all, path_ted_cli_debug_set_all);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * UnRegister the fn's for CLI and hook for config show
 | 
						|
 *
 | 
						|
 * @param void
 | 
						|
 *
 | 
						|
 */
 | 
						|
static void path_ted_unregister_vty(void)
 | 
						|
{
 | 
						|
	uninstall_element(VIEW_NODE, &show_pathd_ted_db_cmd);
 | 
						|
	uninstall_element(SR_TRAFFIC_ENG_NODE, &path_ted_on_cmd);
 | 
						|
	uninstall_element(SR_TRAFFIC_ENG_NODE, &no_path_ted_cmd);
 | 
						|
	uninstall_element(SR_TRAFFIC_ENG_NODE, &path_ted_import_cmd);
 | 
						|
	uninstall_element(SR_TRAFFIC_ENG_NODE, &no_path_ted_import_cmd);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Ask igp for a complete TED so far
 | 
						|
 *
 | 
						|
 * @param void
 | 
						|
 *
 | 
						|
 * @return		zclient status
 | 
						|
 */
 | 
						|
enum zclient_send_status path_ted_link_state_sync(void)
 | 
						|
{
 | 
						|
	enum zclient_send_status status;
 | 
						|
 | 
						|
	status = ls_request_sync(zclient);
 | 
						|
	if (status == -1) {
 | 
						|
		PATH_TED_ERROR(
 | 
						|
			"%s: PATHD-TED: Opaque error asking for TED sync ",
 | 
						|
			__func__);
 | 
						|
		return status;
 | 
						|
	} else {
 | 
						|
		PATH_TED_DEBUG("%s: PATHD-TED: Opaque asked for TED sync ",
 | 
						|
			       __func__);
 | 
						|
	}
 | 
						|
	thread_add_timer(ted_state_g.main, path_ted_timer_handler_sync,
 | 
						|
			 &ted_state_g, ted_state_g.link_state_delay_interval,
 | 
						|
			 &ted_state_g.t_link_state_sync);
 | 
						|
 | 
						|
	return status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Timer cb for check link state sync
 | 
						|
 *
 | 
						|
 * @param thread	Current thread
 | 
						|
 *
 | 
						|
 * @return		status
 | 
						|
 */
 | 
						|
int path_ted_timer_handler_sync(struct thread *thread)
 | 
						|
{
 | 
						|
	/* data unpacking */
 | 
						|
	struct ted_state *data = THREAD_ARG(thread);
 | 
						|
 | 
						|
	assert(data != NULL);
 | 
						|
	/* Retry the sync */
 | 
						|
	return path_ted_link_state_sync();
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * refresg segment list and create timer to keep up updated
 | 
						|
 *
 | 
						|
 * @param void
 | 
						|
 *
 | 
						|
 * @return		status
 | 
						|
 */
 | 
						|
int path_ted_segment_list_refresh(void)
 | 
						|
{
 | 
						|
	int status = 0;
 | 
						|
 | 
						|
	path_ted_timer_refresh_cancel();
 | 
						|
	thread_add_timer(ted_state_g.main, path_ted_timer_handler_refresh,
 | 
						|
			 &ted_state_g,
 | 
						|
			 ted_state_g.segment_list_refresh_interval,
 | 
						|
			 &ted_state_g.t_segment_list_refresh);
 | 
						|
 | 
						|
	return status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Timer cb for refreshing sid in segment lists
 | 
						|
 *
 | 
						|
 * @param void
 | 
						|
 *
 | 
						|
 * @return		status
 | 
						|
 */
 | 
						|
int path_ted_timer_handler_refresh(struct thread *thread)
 | 
						|
{
 | 
						|
	if (!path_ted_is_initialized())
 | 
						|
		return MPLS_LABEL_NONE;
 | 
						|
 | 
						|
	PATH_TED_DEBUG("%s: PATHD-TED: Refresh sid from current TED", __func__);
 | 
						|
	/* data unpacking */
 | 
						|
	struct ted_state *data = THREAD_ARG(thread);
 | 
						|
 | 
						|
	assert(data != NULL);
 | 
						|
 | 
						|
	srte_policy_update_ted_sid();
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Cancel sync timer
 | 
						|
 *
 | 
						|
 * @param void
 | 
						|
 *
 | 
						|
 * @return		void status
 | 
						|
 */
 | 
						|
void path_ted_timer_sync_cancel(void)
 | 
						|
{
 | 
						|
	if (ted_state_g.t_link_state_sync != NULL) {
 | 
						|
		thread_cancel(&ted_state_g.t_link_state_sync);
 | 
						|
		ted_state_g.t_link_state_sync = NULL;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Cancel refresh timer
 | 
						|
 *
 | 
						|
 * @param void
 | 
						|
 *
 | 
						|
 * @return		void status
 | 
						|
 */
 | 
						|
void path_ted_timer_refresh_cancel(void)
 | 
						|
{
 | 
						|
	if (ted_state_g.t_segment_list_refresh != NULL) {
 | 
						|
		thread_cancel(&ted_state_g.t_segment_list_refresh);
 | 
						|
		ted_state_g.t_segment_list_refresh = NULL;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Check which igp is configured
 | 
						|
 *
 | 
						|
 * @param igp who want to check against config-
 | 
						|
 *
 | 
						|
 * @return		status
 | 
						|
 */
 | 
						|
uint32_t path_ted_get_current_igp(uint32_t igp)
 | 
						|
{
 | 
						|
	switch (igp) {
 | 
						|
	case ISIS_L1:
 | 
						|
	case ISIS_L2:
 | 
						|
		if (ted_state_g.import != IMPORT_ISIS) {
 | 
						|
			PATH_TED_ERROR(
 | 
						|
				"%s: [rcv ted] Incorrect igp origin wait (%s) got (%s) ",
 | 
						|
				__func__,
 | 
						|
				PATH_TED_IGP_PRINT(ted_state_g.import),
 | 
						|
				LS_IGP_PRINT(igp));
 | 
						|
			return 1;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case OSPFv2:
 | 
						|
		if (ted_state_g.import != IMPORT_OSPFv2) {
 | 
						|
			PATH_TED_ERROR(
 | 
						|
				"%s: [rcv ted] Incorrect igp origin wait (%s) got (%s) ",
 | 
						|
				__func__,
 | 
						|
				PATH_TED_IGP_PRINT(ted_state_g.import),
 | 
						|
				LS_IGP_PRINT(igp));
 | 
						|
			return 1;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case STATIC:
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 |