mirror of
https://git.proxmox.com/git/mirror_frr
synced 2026-01-04 18:27:53 +00:00
Merge pull request #6789 from volta-networks/feat_ldp_igp_sync
ldpd: Add support for LDP-IGP Synchronization
This commit is contained in:
commit
beb91114ec
@ -59,6 +59,7 @@
|
||||
#include "isisd/isis_errors.h"
|
||||
#include "isisd/isis_tx_queue.h"
|
||||
#include "isisd/isis_nb.h"
|
||||
#include "isisd/isis_ldp_sync.h"
|
||||
|
||||
DEFINE_QOBJ_TYPE(isis_circuit)
|
||||
|
||||
@ -1280,6 +1281,7 @@ struct isis_circuit *isis_circuit_create(struct isis_area *area,
|
||||
isis_circuit_if_bind(circuit, ifp);
|
||||
if (circuit->area->mta && circuit->area->mta->status)
|
||||
isis_link_params_update(circuit, ifp);
|
||||
|
||||
return circuit;
|
||||
}
|
||||
|
||||
@ -1350,11 +1352,16 @@ ferr_r isis_circuit_metric_set(struct isis_circuit *circuit, int level,
|
||||
return ferr_cfg_invalid("metric %d too large for narrow metric",
|
||||
metric);
|
||||
|
||||
circuit->te_metric[level - 1] = metric;
|
||||
circuit->metric[level - 1] = metric;
|
||||
|
||||
if (circuit->area)
|
||||
lsp_regenerate_schedule(circuit->area, level, 0);
|
||||
/* inform ldp-sync of metric change
|
||||
* if ldp-sync is running need to save metric
|
||||
* and restore new values after ldp-sync completion.
|
||||
*/
|
||||
if (isis_ldp_sync_if_metric_config(circuit, level, metric)) {
|
||||
circuit->te_metric[level - 1] = metric;
|
||||
circuit->metric[level - 1] = metric;
|
||||
if (circuit->area)
|
||||
lsp_regenerate_schedule(circuit->area, level, 0);
|
||||
}
|
||||
return ferr_ok();
|
||||
}
|
||||
|
||||
|
||||
@ -139,6 +139,7 @@ struct isis_circuit {
|
||||
uint8_t flags;
|
||||
bool disable_threeway_adj;
|
||||
struct bfd_info *bfd_info;
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
/*
|
||||
* Counters as in 10589--11.2.5.9
|
||||
*/
|
||||
|
||||
180
isisd/isis_cli.c
180
isisd/isis_cli.c
@ -2386,6 +2386,178 @@ void cli_show_isis_log_adjacency(struct vty *vty, struct lyd_node *dnode,
|
||||
vty_out(vty, " log-adjacency-changes\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-isisd:isis/instance/mpls/ldp-sync
|
||||
*/
|
||||
DEFPY(isis_mpls_ldp_sync, isis_mpls_ldp_sync_cmd, "mpls ldp-sync",
|
||||
MPLS_STR MPLS_LDP_SYNC_STR)
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "./mpls/ldp-sync", NB_OP_CREATE, NULL);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
DEFPY(no_isis_mpls_ldp_sync, no_isis_mpls_ldp_sync_cmd, "no mpls ldp-sync",
|
||||
NO_STR MPLS_STR NO_MPLS_LDP_SYNC_STR)
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "./mpls/ldp-sync", NB_OP_DESTROY, NULL);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
void cli_show_isis_mpls_ldp_sync(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults)
|
||||
{
|
||||
vty_out(vty, " mpls ldp-sync\n");
|
||||
}
|
||||
|
||||
DEFPY(isis_mpls_ldp_sync_holddown, isis_mpls_ldp_sync_holddown_cmd,
|
||||
"mpls ldp-sync holddown (0-10000)",
|
||||
MPLS_STR MPLS_LDP_SYNC_STR
|
||||
"Time to wait for LDP-SYNC to occur before restoring interface metric\n"
|
||||
"Time in seconds\n")
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "./mpls/ldp-sync/holddown", NB_OP_MODIFY,
|
||||
holddown_str);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
DEFPY(no_isis_mpls_ldp_sync_holddown, no_isis_mpls_ldp_sync_holddown_cmd,
|
||||
"no mpls ldp-sync holddown [<(1-10000)>]",
|
||||
NO_STR MPLS_STR MPLS_LDP_SYNC_STR NO_MPLS_LDP_SYNC_HOLDDOWN_STR)
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "./mpls/ldp-sync/holddown", NB_OP_DESTROY,
|
||||
NULL);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
void cli_show_isis_mpls_ldp_sync_holddown(struct vty *vty,
|
||||
struct lyd_node *dnode,
|
||||
bool show_defaults)
|
||||
{
|
||||
vty_out(vty, " mpls ldp-sync holddown %s\n",
|
||||
yang_dnode_get_string(dnode, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-interface:lib/interface/frr-isisd:isis/mpls/ldp-sync
|
||||
*/
|
||||
DEFPY(isis_mpls_if_ldp_sync, isis_mpls_if_ldp_sync_cmd,
|
||||
"[no] isis mpls ldp-sync",
|
||||
NO_STR "IS-IS routing protocol\n" MPLS_STR MPLS_LDP_SYNC_STR)
|
||||
{
|
||||
const struct lyd_node *dnode;
|
||||
struct interface *ifp;
|
||||
|
||||
dnode = yang_dnode_get(vty->candidate_config->dnode,
|
||||
"%s/frr-isisd:isis", VTY_CURR_XPATH);
|
||||
if (dnode == NULL) {
|
||||
vty_out(vty, "ISIS is not enabled on this circuit\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
|
||||
if (if_is_loopback(ifp)) {
|
||||
vty_out(vty, "ldp-sync does not run on loopback interface\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (ifp->vrf_id != VRF_DEFAULT) {
|
||||
vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/ldp-sync",
|
||||
NB_OP_MODIFY, no ? "false" : "true");
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
|
||||
void cli_show_isis_mpls_if_ldp_sync(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults)
|
||||
{
|
||||
if (!yang_dnode_get_bool(dnode, NULL))
|
||||
vty_out(vty, " no");
|
||||
|
||||
vty_out(vty, " isis mpls ldp-sync\n");
|
||||
}
|
||||
|
||||
DEFPY(isis_mpls_if_ldp_sync_holddown, isis_mpls_if_ldp_sync_holddown_cmd,
|
||||
"isis mpls ldp-sync holddown (0-10000)",
|
||||
"IS-IS routing protocol\n" MPLS_STR MPLS_LDP_SYNC_STR
|
||||
"Time to wait for LDP-SYNC to occur before restoring interface metric\n"
|
||||
"Time in seconds\n")
|
||||
{
|
||||
const struct lyd_node *dnode;
|
||||
struct interface *ifp;
|
||||
|
||||
dnode = yang_dnode_get(vty->candidate_config->dnode,
|
||||
"%s/frr-isisd:isis", VTY_CURR_XPATH);
|
||||
if (dnode == NULL) {
|
||||
vty_out(vty, "ISIS is not enabled on this circuit\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
|
||||
if (if_is_loopback(ifp)) {
|
||||
vty_out(vty, "ldp-sync does not run on loopback interface\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (ifp->vrf_id != VRF_DEFAULT) {
|
||||
vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/holddown",
|
||||
NB_OP_MODIFY, holddown_str);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
DEFPY(no_isis_mpls_if_ldp_sync_holddown, no_isis_mpls_if_ldp_sync_holddown_cmd,
|
||||
"no isis mpls ldp-sync holddown [<(1-10000)>]",
|
||||
NO_STR "IS-IS routing protocol\n" MPLS_STR NO_MPLS_LDP_SYNC_STR
|
||||
NO_MPLS_LDP_SYNC_HOLDDOWN_STR)
|
||||
{
|
||||
const struct lyd_node *dnode;
|
||||
struct interface *ifp;
|
||||
|
||||
dnode = yang_dnode_get(vty->candidate_config->dnode,
|
||||
"%s/frr-isisd:isis", VTY_CURR_XPATH);
|
||||
if (dnode == NULL) {
|
||||
vty_out(vty, "ISIS is not enabled on this circuit\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
|
||||
if (if_is_loopback(ifp)) {
|
||||
vty_out(vty, "ldp-sync does not run on loopback interface\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (ifp->vrf_id != VRF_DEFAULT) {
|
||||
vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/holddown",
|
||||
NB_OP_DESTROY, NULL);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
void cli_show_isis_mpls_if_ldp_sync_holddown(struct vty *vty,
|
||||
struct lyd_node *dnode,
|
||||
bool show_defaults)
|
||||
{
|
||||
vty_out(vty, " isis mpls ldp-sync holddown %s\n",
|
||||
yang_dnode_get_string(dnode, NULL));
|
||||
}
|
||||
|
||||
void isis_cli_init(void)
|
||||
{
|
||||
install_element(CONFIG_NODE, &router_isis_cmd);
|
||||
@ -2489,6 +2661,14 @@ void isis_cli_init(void)
|
||||
install_element(INTERFACE_NODE, &no_isis_priority_cmd);
|
||||
|
||||
install_element(ISIS_NODE, &log_adj_changes_cmd);
|
||||
|
||||
install_element(ISIS_NODE, &isis_mpls_ldp_sync_cmd);
|
||||
install_element(ISIS_NODE, &no_isis_mpls_ldp_sync_cmd);
|
||||
install_element(ISIS_NODE, &isis_mpls_ldp_sync_holddown_cmd);
|
||||
install_element(ISIS_NODE, &no_isis_mpls_ldp_sync_holddown_cmd);
|
||||
install_element(INTERFACE_NODE, &isis_mpls_if_ldp_sync_cmd);
|
||||
install_element(INTERFACE_NODE, &isis_mpls_if_ldp_sync_holddown_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_mpls_if_ldp_sync_holddown_cmd);
|
||||
}
|
||||
|
||||
#endif /* ifndef FABRICD */
|
||||
|
||||
788
isisd/isis_ldp_sync.c
Normal file
788
isisd/isis_ldp_sync.c
Normal file
@ -0,0 +1,788 @@
|
||||
/**
|
||||
* isis_ldp_sync.c: ISIS LDP-IGP Sync handling routines
|
||||
* 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 General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "monotime.h"
|
||||
#include "memory.h"
|
||||
#include "thread.h"
|
||||
#include "prefix.h"
|
||||
#include "table.h"
|
||||
#include "vty.h"
|
||||
#include "command.h"
|
||||
#include "plist.h"
|
||||
#include "log.h"
|
||||
#include "zclient.h"
|
||||
#include <lib/json.h>
|
||||
#include "defaults.h"
|
||||
#include "ldp_sync.h"
|
||||
|
||||
#include "isisd/isis_constants.h"
|
||||
#include "isisd/isis_common.h"
|
||||
#include "isisd/isis_flags.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
#include "isisd/isis_pdu.h"
|
||||
#include "isisd/isis_network.h"
|
||||
#include "isisd/isis_misc.h"
|
||||
#include "isisd/isis_constants.h"
|
||||
#include "isisd/isis_adjacency.h"
|
||||
#include "isisd/isis_dr.h"
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_csm.h"
|
||||
#include "isisd/isis_events.h"
|
||||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/isis_errors.h"
|
||||
#include "isisd/isis_tx_queue.h"
|
||||
#include "isisd/isis_nb.h"
|
||||
#include "isisd/isis_ldp_sync.h"
|
||||
|
||||
extern struct zclient *zclient;
|
||||
|
||||
/*
|
||||
* LDP-SYNC msg between IGP and LDP
|
||||
*/
|
||||
int isis_ldp_sync_state_update(struct ldp_igp_sync_if_state state)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct isis_circuit *circuit = NULL;
|
||||
struct isis_area *area;
|
||||
struct listnode *node;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
/* if isis is not enabled or LDP-SYNC is not configured ignore */
|
||||
if (!isis ||
|
||||
!CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
|
||||
return 0;
|
||||
|
||||
/* lookup circuit */
|
||||
ifp = if_lookup_by_index(state.ifindex, VRF_DEFAULT);
|
||||
if (ifp == NULL)
|
||||
return 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
|
||||
circuit = circuit_lookup_by_ifp(ifp, area->circuit_list);
|
||||
if (circuit != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
/* if isis is not enabled or LDP-SYNC is not configured ignore */
|
||||
if (circuit == NULL ||
|
||||
!CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
|
||||
return 0;
|
||||
|
||||
/* received ldp-sync interface state from LDP */
|
||||
ils_debug("ldp_sync: rcvd %s from LDP if %s",
|
||||
state.sync_start ? "sync-start" : "sync-complete", ifp->name);
|
||||
if (state.sync_start)
|
||||
isis_ldp_sync_if_start(circuit, false);
|
||||
else
|
||||
isis_ldp_sync_if_complete(circuit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isis_ldp_sync_announce_update(struct ldp_igp_sync_announce announce)
|
||||
{
|
||||
struct isis_area *area;
|
||||
struct listnode *node;
|
||||
struct vrf *vrf;
|
||||
struct interface *ifp;
|
||||
struct isis_circuit *circuit;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
/* if isis is not enabled or LDP-SYNC is not configured ignore */
|
||||
if (!isis ||
|
||||
!CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
|
||||
return 0;
|
||||
|
||||
if (announce.proto != ZEBRA_ROUTE_LDP)
|
||||
return 0;
|
||||
|
||||
ils_debug("ldp_sync: rcvd announce from LDP");
|
||||
|
||||
/* LDP just started up:
|
||||
* set cost to LSInfinity
|
||||
* send request to LDP for LDP-SYNC state for each interface
|
||||
* start hello timer
|
||||
*/
|
||||
vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
|
||||
circuit = circuit_lookup_by_ifp(ifp,
|
||||
area->circuit_list);
|
||||
if (circuit == NULL)
|
||||
continue;
|
||||
isis_ldp_sync_if_start(circuit, true);
|
||||
}
|
||||
}
|
||||
|
||||
THREAD_TIMER_OFF(isis->ldp_sync_cmd.t_hello);
|
||||
isis->ldp_sync_cmd.t_hello = NULL;
|
||||
isis->ldp_sync_cmd.sequence = 0;
|
||||
isis_ldp_sync_hello_timer_add();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isis_ldp_sync_hello_update(struct ldp_igp_sync_hello hello)
|
||||
{
|
||||
struct isis_area *area;
|
||||
struct listnode *node;
|
||||
struct vrf *vrf;
|
||||
struct interface *ifp;
|
||||
struct isis_circuit *circuit;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
/* if isis is not enabled or LDP-SYNC is not configured ignore */
|
||||
if (!isis ||
|
||||
!CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
|
||||
return 0;
|
||||
|
||||
if (hello.proto != ZEBRA_ROUTE_LDP)
|
||||
return 0;
|
||||
|
||||
/* Received Hello from LDP:
|
||||
* if current sequence number is greater than received hello
|
||||
* sequence number then assume LDP restarted
|
||||
* set cost to LSInfinity
|
||||
* send request to LDP for LDP-SYNC state for each interface
|
||||
* else all is fine just restart hello timer
|
||||
*/
|
||||
if (hello.sequence == 0)
|
||||
/* rolled over */
|
||||
isis->ldp_sync_cmd.sequence = 0;
|
||||
|
||||
if (isis->ldp_sync_cmd.sequence > hello.sequence) {
|
||||
zlog_err("ldp_sync: LDP restarted");
|
||||
|
||||
vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node,
|
||||
area)) {
|
||||
circuit = circuit_lookup_by_ifp(ifp,
|
||||
area->circuit_list);
|
||||
if (circuit == NULL)
|
||||
continue;
|
||||
isis_ldp_sync_if_start(circuit, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
THREAD_TIMER_OFF(isis->ldp_sync_cmd.t_hello);
|
||||
isis_ldp_sync_hello_timer_add();
|
||||
}
|
||||
isis->ldp_sync_cmd.sequence = hello.sequence;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isis_ldp_sync_state_req_msg(struct isis_circuit *circuit)
|
||||
{
|
||||
struct ldp_igp_sync_if_state_req request;
|
||||
struct interface *ifp = circuit->interface;
|
||||
|
||||
ils_debug("ldp_sync: send state request to LDP for %s",
|
||||
ifp->name);
|
||||
|
||||
strlcpy(request.name, ifp->name, sizeof(ifp->name));
|
||||
request.proto = LDP_IGP_SYNC_IF_STATE_REQUEST;
|
||||
request.ifindex = ifp->ifindex;
|
||||
|
||||
zclient_send_opaque(zclient, LDP_IGP_SYNC_IF_STATE_REQUEST,
|
||||
(uint8_t *)&request, sizeof(request));
|
||||
}
|
||||
|
||||
/*
|
||||
* LDP-SYNC general interface routines
|
||||
*/
|
||||
void isis_ldp_sync_if_init(struct isis_circuit *circuit, struct isis *isis)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
struct interface *ifp = circuit->interface;
|
||||
|
||||
/* called when ISIS is configured on an interface
|
||||
* if LDP-IGP Sync is configured globally set state
|
||||
* and if ptop interface LDP LDP-SYNC is enabled
|
||||
*/
|
||||
ils_debug("ldp_sync: init if %s ", ifp->name);
|
||||
if (circuit->ldp_sync_info == NULL)
|
||||
circuit->ldp_sync_info = ldp_sync_info_create();
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
/* specifed on interface overrides global config. */
|
||||
if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
|
||||
ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown;
|
||||
|
||||
if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG))
|
||||
ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
|
||||
|
||||
if ((circuit->circ_type == CIRCUIT_T_P2P || if_is_pointopoint(ifp)) &&
|
||||
ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED)
|
||||
ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
|
||||
}
|
||||
|
||||
void isis_ldp_sync_if_start(struct isis_circuit *circuit,
|
||||
bool send_state_req)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
/* Start LDP-SYNC on this interface:
|
||||
* set cost of interface to LSInfinity so traffic will use different
|
||||
* interface until LDP has learned all labels from peer
|
||||
* start holddown timer if configured
|
||||
* send msg to LDP to get LDP-SYNC state
|
||||
*/
|
||||
if (ldp_sync_info &&
|
||||
ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED &&
|
||||
ldp_sync_info->state != LDP_IGP_SYNC_STATE_NOT_REQUIRED) {
|
||||
ils_debug("ldp_sync: start on if %s state: %s",
|
||||
circuit->interface->name, "Holding down until Sync");
|
||||
ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
|
||||
isis_ldp_sync_set_if_metric(circuit, true);
|
||||
isis_ldp_sync_holddown_timer_add(circuit);
|
||||
|
||||
if (send_state_req)
|
||||
isis_ldp_sync_state_req_msg(circuit);
|
||||
}
|
||||
}
|
||||
|
||||
void isis_ldp_sync_if_complete(struct isis_circuit *circuit)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
/* received sync-complete from LDP:
|
||||
* set state to up
|
||||
* stop timer
|
||||
* restore interface cost to original value
|
||||
*/
|
||||
if (ldp_sync_info && ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED) {
|
||||
if (ldp_sync_info->state == LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP)
|
||||
ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_UP;
|
||||
THREAD_TIMER_OFF(ldp_sync_info->t_holddown);
|
||||
ldp_sync_info->t_holddown = NULL;
|
||||
isis_ldp_sync_set_if_metric(circuit, true);
|
||||
}
|
||||
}
|
||||
|
||||
void isis_ldp_sync_ldp_fail(struct isis_circuit *circuit)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
/* LDP failed to send hello:
|
||||
* stop holddown timer
|
||||
* set cost of interface to LSInfinity so traffic will use different
|
||||
* interface until LDP restarts and has learned all labels from peer
|
||||
*/
|
||||
if (ldp_sync_info &&
|
||||
ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED &&
|
||||
ldp_sync_info->state != LDP_IGP_SYNC_STATE_NOT_REQUIRED) {
|
||||
if (ldp_sync_info->t_holddown != NULL) {
|
||||
THREAD_TIMER_OFF(ldp_sync_info->t_holddown);
|
||||
ldp_sync_info->t_holddown = NULL;
|
||||
}
|
||||
ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
|
||||
isis_ldp_sync_set_if_metric(circuit, true);
|
||||
}
|
||||
}
|
||||
|
||||
void isis_ldp_sync_if_remove(struct isis_circuit *circuit, bool remove)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
|
||||
if (circuit->ldp_sync_info == NULL)
|
||||
return;
|
||||
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
/* Stop LDP-SYNC on this interface:
|
||||
* if holddown timer is running stop it
|
||||
* delete ldp instance on interface
|
||||
* restore metric
|
||||
*/
|
||||
ils_debug("ldp_sync: remove if %s", circuit->interface
|
||||
? circuit->interface->name : "");
|
||||
|
||||
if (ldp_sync_info->t_holddown)
|
||||
THREAD_TIMER_OFF(ldp_sync_info->t_holddown);
|
||||
ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
|
||||
isis_ldp_sync_set_if_metric(circuit, true);
|
||||
if (remove) {
|
||||
/* ISIS instance being removed free ldp-sync info */
|
||||
ldp_sync_info_free((struct ldp_sync_info **)&(ldp_sync_info));
|
||||
circuit->ldp_sync_info = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int isis_ldp_sync_adj_state_change(struct isis_adjacency *adj)
|
||||
{
|
||||
struct isis_circuit *circuit = adj->circuit;
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
if (!isis ||
|
||||
!CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) ||
|
||||
circuit->interface->vrf_id != VRF_DEFAULT ||
|
||||
if_is_loopback(circuit->interface))
|
||||
return 0;
|
||||
|
||||
if (circuit->ldp_sync_info == NULL)
|
||||
isis_ldp_sync_if_init(circuit, isis);
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED)
|
||||
return 0;
|
||||
|
||||
if (adj->adj_state == ISIS_ADJ_UP) {
|
||||
if (circuit->circ_type == CIRCUIT_T_P2P ||
|
||||
if_is_pointopoint(circuit->interface)) {
|
||||
/* If LDP-SYNC is configure on interface then start */
|
||||
ldp_sync_info->state =
|
||||
LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
|
||||
isis_ldp_sync_if_start(circuit, true);
|
||||
} else {
|
||||
/* non ptop link so don't run ldp-sync */
|
||||
ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
|
||||
isis_ldp_sync_set_if_metric(circuit, true);
|
||||
}
|
||||
} else {
|
||||
/* If LDP-SYNC is configure on this interface then stop it */
|
||||
if (circuit->circ_type == CIRCUIT_T_P2P ||
|
||||
if_is_pointopoint(circuit->interface))
|
||||
ldp_sync_info->state =
|
||||
LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
|
||||
else
|
||||
ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
|
||||
|
||||
ils_debug("ldp_sync: down on if %s", circuit->interface->name);
|
||||
ldp_sync_if_down(circuit->ldp_sync_info);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool isis_ldp_sync_if_metric_config(struct isis_circuit *circuit, int level,
|
||||
int metric)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
/* configured interface metric has been changed:
|
||||
* if LDP-IGP Sync is running and metric has been set to LSInfinity
|
||||
* change saved value so when ldp-sync completes proper metric is
|
||||
* restored
|
||||
*/
|
||||
if (isis &&
|
||||
CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) &&
|
||||
ldp_sync_info != NULL) {
|
||||
|
||||
if (CHECK_FLAG(ldp_sync_info->flags,
|
||||
LDP_SYNC_FLAG_SET_METRIC)) {
|
||||
ldp_sync_info->metric[level-1] = metric;
|
||||
ldp_sync_info->metric[level-1] = metric;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void isis_ldp_sync_set_if_metric(struct isis_circuit *circuit, bool run_regen)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
|
||||
/* set interface metric:
|
||||
* if LDP-IGP Sync is starting set metric so interface
|
||||
* is used only as last resort
|
||||
* else restore metric to original value
|
||||
*/
|
||||
if (circuit->ldp_sync_info == NULL || circuit->area == NULL)
|
||||
return;
|
||||
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
if (ldp_sync_if_is_enabled(ldp_sync_info)) {
|
||||
/* if metric already set to LSInfinity just return */
|
||||
if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_SET_METRIC))
|
||||
return;
|
||||
|
||||
SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_SET_METRIC);
|
||||
if (circuit->is_type & IS_LEVEL_1) {
|
||||
if (circuit->area->newmetric) {
|
||||
ldp_sync_info->metric[0] =
|
||||
circuit->te_metric[0];
|
||||
circuit->te_metric[0] = LDP_ISIS_LSINFINITY;
|
||||
} else {
|
||||
ldp_sync_info->metric[0] = circuit->metric[0];
|
||||
circuit->metric[0] = LDP_ISIS_LSINFINITY_NL;
|
||||
}
|
||||
}
|
||||
if (circuit->is_type & IS_LEVEL_2) {
|
||||
if (circuit->area->newmetric) {
|
||||
ldp_sync_info->metric[1] =
|
||||
circuit->te_metric[1];
|
||||
circuit->te_metric[1] = LDP_ISIS_LSINFINITY;
|
||||
} else {
|
||||
ldp_sync_info->metric[1] = circuit->metric[1];
|
||||
circuit->metric[1] = LDP_ISIS_LSINFINITY_NL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* if metric already restored just return */
|
||||
if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_SET_METRIC))
|
||||
return;
|
||||
|
||||
UNSET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_SET_METRIC);
|
||||
if (circuit->is_type & IS_LEVEL_1) {
|
||||
circuit->te_metric[0] = ldp_sync_info->metric[0];
|
||||
circuit->metric[0] = ldp_sync_info->metric[0];
|
||||
}
|
||||
if (circuit->is_type & IS_LEVEL_2) {
|
||||
circuit->te_metric[1] = ldp_sync_info->metric[1];
|
||||
circuit->metric[1] = ldp_sync_info->metric[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (run_regen)
|
||||
lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LDP-SYNC holddown timer routines
|
||||
*/
|
||||
static int isis_ldp_sync_holddown_timer(struct thread *thread)
|
||||
{
|
||||
struct isis_circuit *circuit;
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
|
||||
/* holddown timer expired:
|
||||
* didn't receive msg from LDP indicating sync-complete
|
||||
* restore interface cost to original value
|
||||
*/
|
||||
circuit = THREAD_ARG(thread);
|
||||
if (circuit->ldp_sync_info == NULL)
|
||||
return 0;
|
||||
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_UP;
|
||||
ldp_sync_info->t_holddown = NULL;
|
||||
|
||||
ils_debug("ldp_sync: holddown timer expired for %s state:sync achieved",
|
||||
circuit->interface->name);
|
||||
|
||||
isis_ldp_sync_set_if_metric(circuit, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isis_ldp_sync_holddown_timer_add(struct isis_circuit *circuit)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
/* Start holddown timer:
|
||||
* this timer is used to keep interface cost at LSInfinity
|
||||
* once expires returns cost to original value
|
||||
* if timer is already running or holddown time is off just return
|
||||
*/
|
||||
if (ldp_sync_info->t_holddown ||
|
||||
ldp_sync_info->holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT)
|
||||
return;
|
||||
|
||||
ils_debug("ldp_sync: start holddown timer for %s time %d",
|
||||
circuit->interface->name, ldp_sync_info->holddown);
|
||||
|
||||
thread_add_timer(master, isis_ldp_sync_holddown_timer,
|
||||
circuit, ldp_sync_info->holddown,
|
||||
&ldp_sync_info->t_holddown);
|
||||
}
|
||||
|
||||
/*
|
||||
* LDP-SYNC hello timer routines
|
||||
*/
|
||||
static int isis_ldp_sync_hello_timer(struct thread *thread)
|
||||
{
|
||||
struct isis_area *area;
|
||||
struct listnode *node;
|
||||
struct isis_circuit *circuit;
|
||||
struct interface *ifp;
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
if (!isis)
|
||||
return 0;
|
||||
|
||||
/* hello timer expired:
|
||||
* didn't receive hello msg from LDP
|
||||
* set cost of all interfaces to LSInfinity
|
||||
*/
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
|
||||
circuit = circuit_lookup_by_ifp(ifp,
|
||||
area->circuit_list);
|
||||
if (circuit == NULL)
|
||||
continue;
|
||||
|
||||
isis_ldp_sync_ldp_fail(circuit);
|
||||
}
|
||||
}
|
||||
|
||||
zlog_debug("ldp_sync: hello timer expired, LDP down");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isis_ldp_sync_hello_timer_add(void)
|
||||
{
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
/* Start hello timer:
|
||||
* this timer is used to make sure LDP is up
|
||||
* if expires set interface cost to LSInfinity
|
||||
*/
|
||||
if (!isis ||
|
||||
!CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
|
||||
return;
|
||||
|
||||
thread_add_timer(master, isis_ldp_sync_hello_timer,
|
||||
NULL, LDP_IGP_SYNC_HELLO_TIMEOUT,
|
||||
&isis->ldp_sync_cmd.t_hello);
|
||||
}
|
||||
|
||||
/*
|
||||
* LDP-SYNC routes used by set commands.
|
||||
*/
|
||||
|
||||
void isis_if_set_ldp_sync_enable(struct isis_circuit *circuit)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
/* called when setting LDP-SYNC at the global level:
|
||||
* specifed on interface overrides global config
|
||||
* if ptop link send msg to LDP indicating ldp-sync enabled
|
||||
*/
|
||||
if (!isis || if_is_loopback(circuit->interface))
|
||||
return;
|
||||
|
||||
if (CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
|
||||
if (circuit->ldp_sync_info == NULL)
|
||||
isis_ldp_sync_if_init(circuit, isis);
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
/* config on interface, overrides global config. */
|
||||
if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG))
|
||||
if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED)
|
||||
return;
|
||||
|
||||
ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
|
||||
ils_debug("ldp_sync: enable if %s", circuit->interface->name);
|
||||
|
||||
/* send message to LDP if ptop link */
|
||||
if (circuit->circ_type == CIRCUIT_T_P2P ||
|
||||
if_is_pointopoint(circuit->interface)) {
|
||||
ldp_sync_info->state =
|
||||
LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
|
||||
isis_ldp_sync_state_req_msg(circuit);
|
||||
} else {
|
||||
ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
|
||||
zlog_debug("ldp_sync: Sync only runs on P2P links %s",
|
||||
circuit->interface->name);
|
||||
}
|
||||
} else
|
||||
/* delete LDP sync even if configured on an interface */
|
||||
isis_ldp_sync_if_remove(circuit, false);
|
||||
}
|
||||
|
||||
void isis_if_set_ldp_sync_holddown(struct isis_circuit *circuit)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
/* called when setting LDP-SYNC at the global level:
|
||||
* specifed on interface overrides global config.
|
||||
*/
|
||||
if (!isis || if_is_loopback(circuit->interface))
|
||||
return;
|
||||
|
||||
if (circuit->ldp_sync_info == NULL)
|
||||
isis_ldp_sync_if_init(circuit, isis);
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
/* config on interface, overrides global config. */
|
||||
if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
|
||||
return;
|
||||
if (CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN))
|
||||
ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown;
|
||||
else
|
||||
ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
|
||||
}
|
||||
|
||||
void isis_ldp_sync_gbl_exit(bool remove)
|
||||
{
|
||||
struct isis_area *area;
|
||||
struct listnode *node;
|
||||
struct isis_circuit *circuit;
|
||||
struct interface *ifp;
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
/* if you delete LDP-SYNC at a gobal level is clears all LDP-SYNC
|
||||
* configuration, even interface configuration
|
||||
*/
|
||||
if (isis &&
|
||||
CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
|
||||
/* register with opaque client to recv LDP-IGP Sync msgs */
|
||||
zclient_unregister_opaque(zclient,
|
||||
LDP_IGP_SYNC_IF_STATE_UPDATE);
|
||||
zclient_unregister_opaque(zclient,
|
||||
LDP_IGP_SYNC_ANNOUNCE_UPDATE);
|
||||
zclient_unregister_opaque(zclient, LDP_IGP_SYNC_HELLO_UPDATE);
|
||||
|
||||
/* disable LDP-SYNC globally */
|
||||
UNSET_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE);
|
||||
UNSET_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
|
||||
isis->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
|
||||
THREAD_TIMER_OFF(isis->ldp_sync_cmd.t_hello);
|
||||
isis->ldp_sync_cmd.t_hello = NULL;
|
||||
|
||||
/* remove LDP-SYNC on all ISIS interfaces */
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node,
|
||||
area)) {
|
||||
circuit = circuit_lookup_by_ifp(ifp,
|
||||
area->circuit_list);
|
||||
if (circuit == NULL)
|
||||
continue;
|
||||
isis_ldp_sync_if_remove(circuit, remove);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* LDP-SYNC routines used by show commands.
|
||||
*/
|
||||
|
||||
static void isis_circuit_ldp_sync_print_vty(struct isis_circuit *circuit,
|
||||
struct vty *vty)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
const char *ldp_state;
|
||||
|
||||
if (circuit->ldp_sync_info == NULL ||
|
||||
if_is_loopback(circuit->interface))
|
||||
return;
|
||||
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
vty_out(vty, "%-10s\n", circuit->interface->name);
|
||||
vty_out(vty, " LDP-IGP Synchronization enabled: %s\n",
|
||||
ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED
|
||||
? "yes"
|
||||
: "no");
|
||||
vty_out(vty, " holddown timer in seconds: %u\n",
|
||||
ldp_sync_info->holddown);
|
||||
|
||||
switch (ldp_sync_info->state) {
|
||||
case LDP_IGP_SYNC_STATE_REQUIRED_UP:
|
||||
vty_out(vty, " State: Sync achieved\n");
|
||||
break;
|
||||
case LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP:
|
||||
if (ldp_sync_info->t_holddown != NULL) {
|
||||
struct timeval remain = thread_timer_remain(
|
||||
ldp_sync_info->t_holddown);
|
||||
vty_out(vty,
|
||||
" Holddown timer is running %lld.%03lld remaining\n",
|
||||
(long long)remain.tv_sec,
|
||||
(long long)remain.tv_usec/1000);
|
||||
|
||||
vty_out(vty, " State: Holding down until Sync\n");
|
||||
} else
|
||||
vty_out(vty, " State: Sync not achieved\n");
|
||||
break;
|
||||
case LDP_IGP_SYNC_STATE_NOT_REQUIRED:
|
||||
default:
|
||||
if ((circuit->circ_type != CIRCUIT_T_P2P &&
|
||||
!if_is_pointopoint(circuit->interface)) &&
|
||||
circuit->circ_type != CIRCUIT_T_UNKNOWN)
|
||||
ldp_state = "Sync not required: non-p2p link";
|
||||
else
|
||||
ldp_state = "Sync not required";
|
||||
vty_out(vty, " State: %s\n", ldp_state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DEFUN (show_isis_mpls_ldp_interface,
|
||||
show_isis_mpls_ldp_interface_cmd,
|
||||
"show " PROTO_NAME " mpls ldp-sync [interface <INTERFACE|all>]",
|
||||
SHOW_STR
|
||||
PROTO_HELP
|
||||
MPLS_STR
|
||||
"LDP-IGP Sync information\n"
|
||||
"Interface name\n")
|
||||
{
|
||||
char *ifname = NULL;
|
||||
int idx_intf = 0;
|
||||
struct listnode *anode, *cnode;
|
||||
struct isis_area *area;
|
||||
struct isis_circuit *circuit;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
if (!isis) {
|
||||
vty_out(vty, "IS-IS Routing Process not enabled\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (!CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
|
||||
vty_out(vty, "LDP-sync is disabled\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (argv_find(argv, argc, "INTERFACE", &idx_intf))
|
||||
ifname = argv[idx_intf]->arg;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
|
||||
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit))
|
||||
if (!ifname)
|
||||
isis_circuit_ldp_sync_print_vty(circuit, vty);
|
||||
else if (strcmp(circuit->interface->name, ifname) == 0)
|
||||
isis_circuit_ldp_sync_print_vty(circuit, vty);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void isis_ldp_sync_init(void)
|
||||
{
|
||||
|
||||
/* "show ip isis mpls ldp interface" commands. */
|
||||
install_element(VIEW_NODE, &show_isis_mpls_ldp_interface_cmd);
|
||||
|
||||
/* register for adjacency state changes */
|
||||
hook_register(isis_adj_state_change_hook,
|
||||
isis_ldp_sync_adj_state_change);
|
||||
}
|
||||
54
isisd/isis_ldp_sync.h
Normal file
54
isisd/isis_ldp_sync.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* isis_ldp_sync.h: ISIS LDP-IGP Sync handling routines
|
||||
* 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 General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_ISIS_LDP_SYNC_H
|
||||
#define _ZEBRA_ISIS_LDP_SYNC_H
|
||||
|
||||
#define LDP_ISIS_LSINFINITY 0xFFFFFE /* wide link metric */
|
||||
#define LDP_ISIS_LSINFINITY_NL 62 /* narrow link metric */
|
||||
|
||||
/* Macro to log debug message */
|
||||
#define ils_debug(...) \
|
||||
do { \
|
||||
if (IS_DEBUG_LDP_SYNC) \
|
||||
zlog_debug(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
extern void isis_if_set_ldp_sync_enable(struct isis_circuit *circuit);
|
||||
extern void isis_if_set_ldp_sync_holddown(struct isis_circuit *circuit);
|
||||
extern void isis_ldp_sync_if_init(struct isis_circuit *circuit,
|
||||
struct isis *isis);
|
||||
extern void isis_ldp_sync_if_start(struct isis_circuit *circuit,
|
||||
bool send_state_req);
|
||||
extern void isis_ldp_sync_if_remove(struct isis_circuit *circuit, bool remove);
|
||||
extern void isis_ldp_sync_if_complete(struct isis_circuit *circuit);
|
||||
extern void isis_ldp_sync_holddown_timer_add(struct isis_circuit *circuit);
|
||||
extern void isis_ldp_sync_hello_timer_add(void);
|
||||
extern void isis_ldp_sync_ldp_fail(struct isis_circuit *circuit);
|
||||
extern int isis_ldp_sync_state_update(struct ldp_igp_sync_if_state state);
|
||||
extern int isis_ldp_sync_announce_update(struct ldp_igp_sync_announce announce);
|
||||
extern int isis_ldp_sync_hello_update(struct ldp_igp_sync_hello hello);
|
||||
extern void isis_ldp_sync_state_req_msg(struct isis_circuit *circuit);
|
||||
extern void isis_ldp_sync_set_if_metric(struct isis_circuit *circuit,
|
||||
bool run_regen);
|
||||
extern bool isis_ldp_sync_if_metric_config(struct isis_circuit *circuit,
|
||||
int level, int metric);
|
||||
extern void isis_ldp_sync_init(void);
|
||||
extern void isis_ldp_sync_gbl_exit(bool remove);
|
||||
#endif /* _ZEBRA_ISIS_LDP_SYNC_H */
|
||||
@ -58,6 +58,7 @@
|
||||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/fabricd.h"
|
||||
#include "isisd/isis_nb.h"
|
||||
#include "isisd/isis_ldp_sync.h"
|
||||
|
||||
/* Default configuration file name */
|
||||
#define ISISD_DEFAULT_CONFIG "isisd.conf"
|
||||
@ -264,6 +265,7 @@ int main(int argc, char **argv, char **envp)
|
||||
|
||||
isis_zebra_init(master, instance);
|
||||
isis_bfd_init();
|
||||
isis_ldp_sync_init();
|
||||
fabricd_init();
|
||||
|
||||
frr_config_fork();
|
||||
|
||||
@ -537,6 +537,21 @@ const struct frr_yang_module_info frr_isisd_info = {
|
||||
.modify = isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_modify,
|
||||
},
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-isisd:isis/instance/mpls/ldp-sync",
|
||||
.cbs = {
|
||||
.cli_show = cli_show_isis_mpls_ldp_sync,
|
||||
.create = isis_instance_mpls_ldp_sync_create,
|
||||
.destroy = isis_instance_mpls_ldp_sync_destroy,
|
||||
},
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-isisd:isis/instance/mpls/ldp-sync/holddown",
|
||||
.cbs = {
|
||||
.cli_show = cli_show_isis_mpls_ldp_sync_holddown,
|
||||
.modify = isis_instance_mpls_ldp_sync_holddown_modify,
|
||||
},
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-interface:lib/interface/frr-isisd:isis",
|
||||
.cbs = {
|
||||
@ -905,6 +920,21 @@ const struct frr_yang_module_info frr_isisd_info = {
|
||||
.get_elem = lib_interface_state_isis_event_counters_authentication_fails_get_elem,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-interface:lib/interface/frr-isisd:isis/mpls/ldp-sync",
|
||||
.cbs = {
|
||||
.cli_show = cli_show_isis_mpls_if_ldp_sync,
|
||||
.modify = lib_interface_isis_mpls_ldp_sync_modify,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-interface:lib/interface/frr-isisd:isis/mpls/holddown",
|
||||
.cbs = {
|
||||
.cli_show = cli_show_isis_mpls_if_ldp_sync_holddown,
|
||||
.modify = lib_interface_isis_mpls_holddown_modify,
|
||||
.destroy = lib_interface_isis_mpls_holddown_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = NULL,
|
||||
},
|
||||
|
||||
@ -206,6 +206,9 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int isis_instance_mpls_ldp_sync_destroy(struct nb_cb_destroy_args *args);
|
||||
int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args);
|
||||
int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args);
|
||||
int lib_interface_isis_csnp_interval_level_1_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int lib_interface_isis_csnp_interval_level_2_modify(
|
||||
@ -250,6 +253,9 @@ int lib_interface_isis_multi_topology_ipv6_management_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int lib_interface_isis_multi_topology_ipv6_dstsrc_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int lib_interface_isis_mpls_ldp_sync_modify(struct nb_cb_modify_args *args);
|
||||
int lib_interface_isis_mpls_holddown_modify(struct nb_cb_modify_args *args);
|
||||
int lib_interface_isis_mpls_holddown_destroy(struct nb_cb_destroy_args *args);
|
||||
struct yang_data *
|
||||
lib_interface_state_isis_get_elem(struct nb_cb_get_elem_args *args);
|
||||
const void *lib_interface_state_isis_adjacencies_adjacency_get_next(
|
||||
@ -434,6 +440,16 @@ void cli_show_ip_isis_priority(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
void cli_show_isis_log_adjacency(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
void cli_show_isis_mpls_ldp_sync(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
void cli_show_isis_mpls_ldp_sync_holddown(struct vty *vty,
|
||||
struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
void cli_show_isis_mpls_if_ldp_sync(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
void cli_show_isis_mpls_if_ldp_sync_holddown(struct vty *vty,
|
||||
struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
|
||||
/* Notifications. */
|
||||
void isis_notif_db_overload(const struct isis_area *area, bool overload);
|
||||
|
||||
@ -29,6 +29,8 @@
|
||||
#include "spf_backoff.h"
|
||||
#include "lib_errors.h"
|
||||
#include "vrf.h"
|
||||
#include "zclient.h"
|
||||
#include "ldp_sync.h"
|
||||
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_nb.h"
|
||||
@ -45,6 +47,9 @@
|
||||
#include "isisd/isis_memory.h"
|
||||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/isis_redist.h"
|
||||
#include "isisd/isis_ldp_sync.h"
|
||||
|
||||
extern struct zclient *zclient;
|
||||
|
||||
/*
|
||||
* XPath: /frr-isisd:isis/instance
|
||||
@ -81,6 +86,10 @@ int isis_instance_destroy(struct nb_cb_destroy_args *args)
|
||||
area = nb_running_unset_entry(args->dnode);
|
||||
isis_area_destroy(area);
|
||||
|
||||
/* remove ldp-sync config */
|
||||
if (area->isis->vrf_id == VRF_DEFAULT)
|
||||
isis_ldp_sync_gbl_exit(true);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
@ -1825,6 +1834,113 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_mo
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-isisd:isis/instance/mpls/ldp-sync
|
||||
*/
|
||||
int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args)
|
||||
{
|
||||
struct isis_area *area;
|
||||
struct listnode *node;
|
||||
struct isis_circuit *circuit;
|
||||
struct interface *ifp;
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
if (isis == NULL)
|
||||
return NB_ERR_VALIDATION;
|
||||
break;
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
/* register with opaque client to recv LDP-IGP Sync msgs */
|
||||
zclient_register_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE);
|
||||
zclient_register_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE);
|
||||
zclient_register_opaque(zclient, LDP_IGP_SYNC_HELLO_UPDATE);
|
||||
|
||||
if (!CHECK_FLAG(isis->ldp_sync_cmd.flags,
|
||||
LDP_SYNC_FLAG_ENABLE)) {
|
||||
SET_FLAG(isis->ldp_sync_cmd.flags,
|
||||
LDP_SYNC_FLAG_ENABLE);
|
||||
|
||||
/* turn on LDP-IGP Sync on all ptop ISIS interfaces */
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node,
|
||||
area)) {
|
||||
circuit = circuit_lookup_by_ifp(
|
||||
ifp, area->circuit_list);
|
||||
if (circuit == NULL)
|
||||
continue;
|
||||
isis_if_set_ldp_sync_enable(circuit);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int isis_instance_mpls_ldp_sync_destroy(struct nb_cb_destroy_args *args)
|
||||
{
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
/* remove ldp-sync config */
|
||||
isis_ldp_sync_gbl_exit(false);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-isisd:isis/instance/mpls/ldp-sync/holddown
|
||||
*/
|
||||
int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct isis_area *area;
|
||||
struct listnode *node;
|
||||
struct isis_circuit *circuit;
|
||||
struct interface *ifp;
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
uint16_t holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
if (isis == NULL)
|
||||
return NB_ERR_VALIDATION;
|
||||
break;
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
holddown = yang_dnode_get_uint16(args->dnode, NULL);
|
||||
|
||||
if (holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT)
|
||||
UNSET_FLAG(isis->ldp_sync_cmd.flags,
|
||||
LDP_SYNC_FLAG_HOLDDOWN);
|
||||
else
|
||||
SET_FLAG(isis->ldp_sync_cmd.flags,
|
||||
LDP_SYNC_FLAG_HOLDDOWN);
|
||||
isis->ldp_sync_cmd.holddown = holddown;
|
||||
|
||||
/* set holddown time on all ISIS interfaces */
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node,
|
||||
area)) {
|
||||
circuit = circuit_lookup_by_ifp(ifp,
|
||||
area->circuit_list);
|
||||
if (circuit == NULL)
|
||||
continue;
|
||||
isis_if_set_ldp_sync_holddown(circuit);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-interface:lib/interface/frr-isisd:isis
|
||||
*/
|
||||
@ -1915,6 +2031,9 @@ int lib_interface_isis_destroy(struct nb_cb_destroy_args *args)
|
||||
if (!circuit)
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
|
||||
/* remove ldp-sync config */
|
||||
isis_ldp_sync_if_remove(circuit, true);
|
||||
|
||||
/* disable both AFs for this circuit. this will also update the
|
||||
* CSM state by sending an ISIS_DISABLED signal. If there is no
|
||||
* area associated to the circuit there is nothing to do
|
||||
@ -2646,3 +2765,130 @@ int lib_interface_isis_multi_topology_ipv6_dstsrc_modify(
|
||||
args->event, args->dnode, args->errmsg, args->errmsg_len,
|
||||
ISIS_MT_IPV6_DSTSRC);
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-interface:lib/interface/frr-isisd:isis/mpls/ldp-sync
|
||||
*/
|
||||
int lib_interface_isis_mpls_ldp_sync_modify(struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct isis_circuit *circuit;
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
bool ldp_sync_enable;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
if (isis == NULL)
|
||||
return NB_ERR_VALIDATION;
|
||||
break;
|
||||
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
circuit = nb_running_get_entry(args->dnode, NULL, true);
|
||||
ldp_sync_enable = yang_dnode_get_bool(args->dnode, NULL);
|
||||
|
||||
if (circuit->ldp_sync_info == NULL)
|
||||
isis_ldp_sync_if_init(circuit, isis);
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
if (ldp_sync_enable) {
|
||||
/* enable LDP-SYNC on an interface
|
||||
* if ptop interface send message to LDP to get state
|
||||
*/
|
||||
SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
|
||||
ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
|
||||
if (circuit->circ_type == CIRCUIT_T_P2P) {
|
||||
ldp_sync_info->state =
|
||||
LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
|
||||
isis_ldp_sync_state_req_msg(circuit);
|
||||
} else {
|
||||
zlog_debug("ldp_sync: only runs on P2P links %s",
|
||||
circuit->interface->name);
|
||||
ldp_sync_info->state =
|
||||
LDP_IGP_SYNC_STATE_NOT_REQUIRED;
|
||||
}
|
||||
} else {
|
||||
/* disable LDP-SYNC on an interface
|
||||
* stop holddown timer if running
|
||||
* restore isis metric
|
||||
*/
|
||||
SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
|
||||
ldp_sync_info->enabled = LDP_IGP_SYNC_DEFAULT;
|
||||
ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
|
||||
THREAD_TIMER_OFF(ldp_sync_info->t_holddown);
|
||||
ldp_sync_info->t_holddown = NULL;
|
||||
isis_ldp_sync_set_if_metric(circuit, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-interface:lib/interface/frr-isisd:isis/mpls/holddown
|
||||
*/
|
||||
int lib_interface_isis_mpls_holddown_modify(struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct isis_circuit *circuit;
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
uint16_t holddown;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
if (isis == NULL)
|
||||
return NB_ERR_VALIDATION;
|
||||
break;
|
||||
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
circuit = nb_running_get_entry(args->dnode, NULL, true);
|
||||
holddown = yang_dnode_get_uint16(args->dnode, NULL);
|
||||
|
||||
if (circuit->ldp_sync_info == NULL)
|
||||
isis_ldp_sync_if_init(circuit, isis);
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
|
||||
SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN);
|
||||
ldp_sync_info->holddown = holddown;
|
||||
break;
|
||||
}
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int lib_interface_isis_mpls_holddown_destroy(struct nb_cb_destroy_args *args)
|
||||
{
|
||||
struct isis_circuit *circuit;
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
if (isis == NULL)
|
||||
return NB_ERR_VALIDATION;
|
||||
circuit = nb_running_get_entry(args->dnode, NULL, true);
|
||||
if (circuit->ldp_sync_info == NULL)
|
||||
return NB_ERR_VALIDATION;
|
||||
|
||||
break;
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
circuit = nb_running_get_entry(args->dnode, NULL, true);
|
||||
ldp_sync_info = circuit->ldp_sync_info;
|
||||
UNSET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN);
|
||||
|
||||
if (CHECK_FLAG(isis->ldp_sync_cmd.flags,
|
||||
LDP_SYNC_FLAG_HOLDDOWN))
|
||||
ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown;
|
||||
else
|
||||
ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
|
||||
break;
|
||||
}
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
@ -52,6 +52,7 @@
|
||||
#include "isisd/isis_adjacency.h"
|
||||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_sr.h"
|
||||
#include "isisd/isis_ldp_sync.h"
|
||||
|
||||
struct zclient *zclient;
|
||||
static struct zclient *zclient_sync;
|
||||
@ -596,6 +597,44 @@ static void isis_zebra_connected(struct zclient *zclient)
|
||||
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
||||
}
|
||||
|
||||
/*
|
||||
* opaque messages between processes
|
||||
*/
|
||||
static int isis_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_opaque_msg info;
|
||||
struct ldp_igp_sync_if_state state;
|
||||
struct ldp_igp_sync_announce announce;
|
||||
struct ldp_igp_sync_hello hello;
|
||||
int ret = 0;
|
||||
|
||||
s = zclient->ibuf;
|
||||
if (zclient_opaque_decode(s, &info) != 0)
|
||||
return -1;
|
||||
|
||||
switch (info.type) {
|
||||
case LDP_IGP_SYNC_IF_STATE_UPDATE:
|
||||
STREAM_GET(&state, s, sizeof(state));
|
||||
ret = isis_ldp_sync_state_update(state);
|
||||
break;
|
||||
case LDP_IGP_SYNC_ANNOUNCE_UPDATE:
|
||||
STREAM_GET(&announce, s, sizeof(announce));
|
||||
ret = isis_ldp_sync_announce_update(announce);
|
||||
break;
|
||||
case LDP_IGP_SYNC_HELLO_UPDATE:
|
||||
STREAM_GET(&hello, s, sizeof(hello));
|
||||
ret = isis_ldp_sync_hello_update(hello);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
stream_failure:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void isis_zebra_init(struct thread_master *master, int instance)
|
||||
{
|
||||
/* Initialize asynchronous zclient. */
|
||||
@ -622,6 +661,8 @@ void isis_zebra_init(struct thread_master *master, int instance)
|
||||
*/
|
||||
zclient_sync->session_id = 1;
|
||||
zclient_sync->privs = &isisd_privs;
|
||||
|
||||
zclient->opaque_msg_handler = isis_opaque_msg_handler;
|
||||
}
|
||||
|
||||
void isis_zebra_stop(void)
|
||||
|
||||
@ -76,6 +76,7 @@ unsigned long debug_flooding;
|
||||
unsigned long debug_bfd;
|
||||
unsigned long debug_tx_queue;
|
||||
unsigned long debug_sr;
|
||||
unsigned long debug_ldp_sync;
|
||||
|
||||
DEFINE_QOBJ_TYPE(isis_area)
|
||||
|
||||
@ -1207,6 +1208,8 @@ void print_debug(struct vty *vty, int flags, int onoff)
|
||||
vty_out(vty, "IS-IS Flooding debugging is %s\n", onoffs);
|
||||
if (flags & DEBUG_BFD)
|
||||
vty_out(vty, "IS-IS BFD debugging is %s\n", onoffs);
|
||||
if (flags & DEBUG_LDP_SYNC)
|
||||
vty_out(vty, "IS-IS ldp-sync debugging is %s\n", onoffs);
|
||||
}
|
||||
|
||||
DEFUN_NOSH (show_debugging,
|
||||
@ -1244,6 +1247,8 @@ DEFUN_NOSH (show_debugging,
|
||||
print_debug(vty, DEBUG_FLOODING, 1);
|
||||
if (IS_DEBUG_BFD)
|
||||
print_debug(vty, DEBUG_BFD, 1);
|
||||
if (IS_DEBUG_LDP_SYNC)
|
||||
print_debug(vty, DEBUG_LDP_SYNC, 1);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1312,6 +1317,10 @@ static int config_write_debug(struct vty *vty)
|
||||
vty_out(vty, "debug " PROTO_NAME " bfd\n");
|
||||
write++;
|
||||
}
|
||||
if (IS_DEBUG_LDP_SYNC) {
|
||||
vty_out(vty, "debug " PROTO_NAME " ldp-sync\n");
|
||||
write++;
|
||||
}
|
||||
write += spf_backoff_write_config(vty);
|
||||
|
||||
return write;
|
||||
@ -1668,11 +1677,32 @@ DEFUN (no_debug_isis_bfd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(show_hostname, show_hostname_cmd,
|
||||
"show " PROTO_NAME " [vrf <NAME|all>] hostname",
|
||||
SHOW_STR PROTO_HELP VRF_CMD_HELP_STR
|
||||
"All VRFs\n"
|
||||
"IS-IS Dynamic hostname mapping\n")
|
||||
DEFUN(debug_isis_ldp_sync, debug_isis_ldp_sync_cmd,
|
||||
"debug " PROTO_NAME " ldp-sync",
|
||||
DEBUG_STR PROTO_HELP PROTO_NAME " interaction with LDP-Sync\n")
|
||||
{
|
||||
debug_ldp_sync |= DEBUG_LDP_SYNC;
|
||||
print_debug(vty, DEBUG_LDP_SYNC, 1);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(no_debug_isis_ldp_sync, no_debug_isis_ldp_sync_cmd,
|
||||
"no debug " PROTO_NAME " ldp-sync",
|
||||
NO_STR UNDEBUG_STR PROTO_HELP PROTO_NAME " interaction with LDP-Sync\n")
|
||||
{
|
||||
debug_ldp_sync &= ~DEBUG_LDP_SYNC;
|
||||
print_debug(vty, DEBUG_LDP_SYNC, 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_hostname,
|
||||
show_hostname_cmd,
|
||||
"show " PROTO_NAME " hostname",
|
||||
SHOW_STR
|
||||
PROTO_HELP
|
||||
"IS-IS Dynamic hostname mapping\n")
|
||||
{
|
||||
struct listnode *node;
|
||||
const char *vrf_name = VRF_DEFAULT_NAME;
|
||||
@ -2830,6 +2860,8 @@ void isis_init(void)
|
||||
install_element(ENABLE_NODE, &no_debug_isis_lsp_sched_cmd);
|
||||
install_element(ENABLE_NODE, &debug_isis_bfd_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_isis_bfd_cmd);
|
||||
install_element(ENABLE_NODE, &debug_isis_ldp_sync_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_isis_ldp_sync_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &debug_isis_adj_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_isis_adj_cmd);
|
||||
@ -2857,6 +2889,8 @@ void isis_init(void)
|
||||
install_element(CONFIG_NODE, &no_debug_isis_lsp_sched_cmd);
|
||||
install_element(CONFIG_NODE, &debug_isis_bfd_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_isis_bfd_cmd);
|
||||
install_element(CONFIG_NODE, &debug_isis_ldp_sync_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_isis_ldp_sync_cmd);
|
||||
|
||||
install_default(ROUTER_NODE);
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
#include "isis_lsp.h"
|
||||
#include "isis_memory.h"
|
||||
#include "qobj.h"
|
||||
#include "ldp_sync.h"
|
||||
|
||||
#ifdef FABRICD
|
||||
static const bool fabricd = true;
|
||||
@ -93,6 +94,7 @@ struct isis {
|
||||
uint32_t circuit_ids_used[8]; /* 256 bits to track circuit ids 1 through 255 */
|
||||
|
||||
struct route_table *ext_info[REDIST_PROTOCOL_COUNT];
|
||||
struct ldp_sync_info_cmd ldp_sync_cmd; /* MPLS LDP-IGP Sync */
|
||||
};
|
||||
|
||||
extern struct isis_master *im;
|
||||
@ -275,6 +277,7 @@ extern unsigned long debug_flooding;
|
||||
extern unsigned long debug_bfd;
|
||||
extern unsigned long debug_tx_queue;
|
||||
extern unsigned long debug_sr;
|
||||
extern unsigned long debug_ldp_sync;
|
||||
|
||||
#define DEBUG_ADJ_PACKETS (1<<0)
|
||||
#define DEBUG_SNP_PACKETS (1<<1)
|
||||
@ -289,6 +292,7 @@ extern unsigned long debug_sr;
|
||||
#define DEBUG_BFD (1<<10)
|
||||
#define DEBUG_TX_QUEUE (1<<11)
|
||||
#define DEBUG_SR (1<<12)
|
||||
#define DEBUG_LDP_SYNC (1 << 13)
|
||||
|
||||
/* Debug related macro. */
|
||||
#define IS_DEBUG_ADJ_PACKETS (debug_adj_pkt & DEBUG_ADJ_PACKETS)
|
||||
@ -304,6 +308,7 @@ extern unsigned long debug_sr;
|
||||
#define IS_DEBUG_BFD (debug_bfd & DEBUG_BFD)
|
||||
#define IS_DEBUG_TX_QUEUE (debug_tx_queue & DEBUG_TX_QUEUE)
|
||||
#define IS_DEBUG_SR (debug_sr & DEBUG_SR)
|
||||
#define IS_DEBUG_LDP_SYNC (debug_ldp_sync & DEBUG_LDP_SYNC)
|
||||
|
||||
#define lsp_debug(...) \
|
||||
do { \
|
||||
|
||||
@ -8,6 +8,7 @@ sbin_PROGRAMS += isisd/isisd
|
||||
dist_examples_DATA += isisd/isisd.conf.sample
|
||||
vtysh_scan += \
|
||||
isisd/isis_cli.c \
|
||||
isisd/isis_ldp_sync.c \
|
||||
isisd/isis_redist.c \
|
||||
isisd/isis_spf.c \
|
||||
isisd/isis_te.c \
|
||||
@ -36,6 +37,7 @@ noinst_HEADERS += \
|
||||
isisd/isis_errors.h \
|
||||
isisd/isis_events.h \
|
||||
isisd/isis_flags.h \
|
||||
isisd/isis_ldp_sync.h \
|
||||
isisd/isis_lsp.h \
|
||||
isisd/isis_memory.h \
|
||||
isisd/isis_misc.h \
|
||||
@ -69,6 +71,7 @@ LIBISIS_SOURCES = \
|
||||
isisd/isis_errors.c \
|
||||
isisd/isis_events.c \
|
||||
isisd/isis_flags.c \
|
||||
isisd/isis_ldp_sync.c \
|
||||
isisd/isis_lsp.c \
|
||||
isisd/isis_memory.c \
|
||||
isisd/isis_misc.c \
|
||||
|
||||
@ -125,6 +125,9 @@ adj_del(struct adj *adj, uint32_t notif_status)
|
||||
switch (adj->source.type) {
|
||||
case HELLO_LINK:
|
||||
RB_REMOVE(ia_adj_head, &adj->source.link.ia->adj_tree, adj);
|
||||
|
||||
if (nbr)
|
||||
ldp_sync_fsm_adj_event(adj, LDP_SYNC_EVT_ADJ_DEL);
|
||||
break;
|
||||
case HELLO_TARGETED:
|
||||
adj->source.target->adj = NULL;
|
||||
|
||||
@ -263,6 +263,9 @@ control_dispatch_imsg(struct thread *thread)
|
||||
|
||||
nbr_clear_ctl(imsg.data);
|
||||
break;
|
||||
case IMSG_CTL_SHOW_LDP_SYNC:
|
||||
ldpe_ldp_sync_ctl(c);
|
||||
break;
|
||||
case IMSG_CTL_LOG_VERBOSE:
|
||||
/* ignore */
|
||||
break;
|
||||
|
||||
@ -378,6 +378,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
|
||||
adj->nbr = nbr;
|
||||
RB_INSERT(nbr_adj_head, &nbr->adj_tree, adj);
|
||||
}
|
||||
ldp_sync_fsm_adj_event(adj, LDP_SYNC_EVT_ADJ_NEW);
|
||||
}
|
||||
adj->ds_tlv = ds_tlv;
|
||||
|
||||
|
||||
417
ldpd/interface.c
417
ldpd/interface.c
@ -23,6 +23,7 @@
|
||||
#include "ldpd.h"
|
||||
#include "ldpe.h"
|
||||
#include "log.h"
|
||||
#include "ldp_debug.h"
|
||||
|
||||
#include "sockopt.h"
|
||||
|
||||
@ -40,6 +41,17 @@ static int if_leave_ipv4_group(struct iface *, struct in_addr *);
|
||||
static int if_join_ipv6_group(struct iface *, struct in6_addr *);
|
||||
static int if_leave_ipv6_group(struct iface *, struct in6_addr *);
|
||||
|
||||
static int ldp_sync_fsm_init(struct iface *iface, int state);
|
||||
static int ldp_sync_act_iface_start_sync(struct iface *iface);
|
||||
static int iface_wait_for_ldp_sync_timer(struct thread *thread);
|
||||
static void start_wait_for_ldp_sync_timer(struct iface *iface);
|
||||
static void stop_wait_for_ldp_sync_timer(struct iface *iface);
|
||||
static int ldp_sync_act_ldp_start_sync(struct iface *iface);
|
||||
static int ldp_sync_act_ldp_complete_sync(struct iface *iface);
|
||||
static int iface_to_oper_nbr_count(struct iface *iface, unsigned int type);
|
||||
static void ldp_sync_get_peer_ldp_id(struct iface *iface,
|
||||
struct in_addr *peer_ldp_id);
|
||||
|
||||
RB_GENERATE(iface_head, iface, entry, iface_compare)
|
||||
|
||||
static __inline int
|
||||
@ -87,6 +99,9 @@ ldpe_if_init(struct iface *iface)
|
||||
iface->ipv6.iface = iface;
|
||||
iface->ipv6.state = IF_STA_DOWN;
|
||||
RB_INIT(ia_adj_head, &iface->ipv6.adj_tree);
|
||||
|
||||
/* LGP IGP Sync */
|
||||
ldp_sync_fsm_init(iface, LDP_SYNC_STA_NOT_ACH);
|
||||
}
|
||||
|
||||
void
|
||||
@ -96,6 +111,8 @@ ldpe_if_exit(struct iface *iface)
|
||||
|
||||
log_debug("%s: interface %s", __func__, iface->name);
|
||||
|
||||
ldp_sync_fsm(iface, LDP_SYNC_EVT_CONFIG_LDP_OFF);
|
||||
|
||||
if (iface->ipv4.state == IF_STA_ACTIVE)
|
||||
if_reset(iface, AF_INET);
|
||||
if (iface->ipv6.state == IF_STA_ACTIVE)
|
||||
@ -138,6 +155,10 @@ if_update_info(struct iface *iface, struct kif *kif)
|
||||
kif->flags & IFF_MULTICAST)
|
||||
iface->type = IF_TYPE_BROADCAST;
|
||||
|
||||
if (ldpd_process == PROC_LDP_ENGINE && iface->operative &&
|
||||
!kif->operative)
|
||||
ldp_sync_fsm(iface, LDP_SYNC_EVT_IFACE_SHUTDOWN);
|
||||
|
||||
/* get index and flags */
|
||||
iface->ifindex = kif->ifindex;
|
||||
iface->operative = kif->operative;
|
||||
@ -426,6 +447,12 @@ if_get_hello_interval(struct iface_af *ia)
|
||||
return (leconf->lhello_interval);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
if_get_wait_for_sync_interval(void)
|
||||
{
|
||||
return (leconf->wait_for_sync_interval);
|
||||
}
|
||||
|
||||
/* timers */
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
@ -484,6 +511,55 @@ if_to_ctl(struct iface_af *ia)
|
||||
return (&ictl);
|
||||
}
|
||||
|
||||
static void
|
||||
ldp_sync_get_peer_ldp_id(struct iface *iface, struct in_addr *peer_ldp_id)
|
||||
{
|
||||
struct iface_af *ia;
|
||||
struct adj *adj;
|
||||
|
||||
if (iface->ipv4.state == IF_STA_ACTIVE) {
|
||||
ia = iface_af_get(iface, AF_INET);
|
||||
RB_FOREACH(adj, ia_adj_head, &ia->adj_tree)
|
||||
if (adj->nbr && adj->nbr->state == NBR_STA_OPER) {
|
||||
*peer_ldp_id = adj->nbr->id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (iface->ipv6.state == IF_STA_ACTIVE) {
|
||||
ia = iface_af_get(iface, AF_INET6);
|
||||
RB_FOREACH(adj, ia_adj_head, &ia->adj_tree)
|
||||
if (adj->nbr && adj->nbr->state == NBR_STA_OPER) {
|
||||
*peer_ldp_id = adj->nbr->id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ctl_ldp_sync *
|
||||
ldp_sync_to_ctl(struct iface *iface)
|
||||
{
|
||||
static struct ctl_ldp_sync ictl;
|
||||
|
||||
memcpy(ictl.name, iface->name, sizeof(ictl.name));
|
||||
ictl.ifindex = iface->ifindex;
|
||||
ictl.in_sync = (iface->ldp_sync.state == LDP_SYNC_STA_ACH);
|
||||
ictl.wait_time = if_get_wait_for_sync_interval();
|
||||
ictl.timer_running = iface->ldp_sync.wait_for_sync_timer ? true : false;
|
||||
|
||||
if (iface->ldp_sync.wait_for_sync_timer)
|
||||
ictl.wait_time_remaining =
|
||||
thread_timer_remain_second(iface->ldp_sync.wait_for_sync_timer);
|
||||
else
|
||||
ictl.wait_time_remaining = 0;
|
||||
|
||||
memset(&ictl.peer_ldp_id, 0, sizeof(ictl.peer_ldp_id));
|
||||
|
||||
ldp_sync_get_peer_ldp_id(iface, &ictl.peer_ldp_id);
|
||||
|
||||
return (&ictl);
|
||||
}
|
||||
|
||||
/* multicast membership sockopts */
|
||||
in_addr_t
|
||||
if_get_ipv4_addr(struct iface *iface)
|
||||
@ -576,3 +652,344 @@ if_leave_ipv6_group(struct iface *iface, struct in6_addr *addr)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
const struct {
|
||||
int state;
|
||||
enum ldp_sync_event event;
|
||||
enum ldp_sync_action action;
|
||||
int new_state;
|
||||
} ldp_sync_fsm_tbl[] = {
|
||||
/* current state event that happened action to take resulting state */
|
||||
/* LDP IGP Sync not achieved */
|
||||
{LDP_SYNC_STA_NOT_ACH, LDP_SYNC_EVT_LDP_SYNC_START, LDP_SYNC_ACT_LDP_START_SYNC, 0},
|
||||
{LDP_SYNC_STA_NOT_ACH, LDP_SYNC_EVT_LDP_SYNC_COMPLETE, LDP_SYNC_ACT_LDP_COMPLETE_SYNC, LDP_SYNC_STA_ACH},
|
||||
{LDP_SYNC_STA_NOT_ACH, LDP_SYNC_EVT_CONFIG_LDP_OFF, LDP_SYNC_ACT_CONFIG_LDP_OFF, 0},
|
||||
{LDP_SYNC_STA_NOT_ACH, LDP_SYNC_EVT_IFACE_SHUTDOWN, LDP_SYNC_ACT_IFACE_SHUTDOWN, 0},
|
||||
{LDP_SYNC_STA_NOT_ACH, LDP_SYNC_EVT_SESSION_CLOSE, LDP_SYNC_ACT_NOTHING, 0},
|
||||
{LDP_SYNC_STA_NOT_ACH, LDP_SYNC_EVT_ADJ_DEL, LDP_SYNC_ACT_NOTHING, 0},
|
||||
{LDP_SYNC_STA_NOT_ACH, LDP_SYNC_EVT_ADJ_NEW, LDP_SYNC_ACT_NOTHING, 0},
|
||||
/* LDP IGP Sync achieved */
|
||||
{LDP_SYNC_STA_ACH, LDP_SYNC_EVT_CONFIG_LDP_OFF, LDP_SYNC_ACT_CONFIG_LDP_OFF, LDP_SYNC_STA_NOT_ACH},
|
||||
{LDP_SYNC_STA_ACH, LDP_SYNC_EVT_LDP_SYNC_COMPLETE, LDP_SYNC_ACT_NOTHING, 0},
|
||||
{LDP_SYNC_STA_ACH, LDP_SYNC_EVT_LDP_SYNC_START, LDP_SYNC_ACT_NOTHING, 0},
|
||||
{LDP_SYNC_STA_ACH, LDP_SYNC_EVT_IFACE_SHUTDOWN, LDP_SYNC_ACT_IFACE_SHUTDOWN, LDP_SYNC_STA_NOT_ACH},
|
||||
{LDP_SYNC_STA_ACH, LDP_SYNC_EVT_SESSION_CLOSE, LDP_SYNC_ACT_IFACE_START_SYNC, LDP_SYNC_STA_NOT_ACH},
|
||||
{LDP_SYNC_STA_ACH, LDP_SYNC_EVT_ADJ_DEL, LDP_SYNC_ACT_IFACE_START_SYNC, LDP_SYNC_STA_NOT_ACH},
|
||||
{LDP_SYNC_STA_ACH, LDP_SYNC_EVT_ADJ_NEW, LDP_SYNC_ACT_NOTHING, 0},
|
||||
{-1, LDP_SYNC_EVT_NOTHING, LDP_SYNC_ACT_NOTHING, 0},
|
||||
};
|
||||
|
||||
const char * const ldp_sync_event_names[] = {
|
||||
"NOTHING",
|
||||
"LDP SYNC START",
|
||||
"LDP SYNC COMPLETE",
|
||||
"CONFIG LDP OFF",
|
||||
"IFACE SYNC START (ADJ DEL)",
|
||||
"IFACE SYNC START (ADJ NEW)",
|
||||
"IFACE SYNC START (SESSION CLOSE)",
|
||||
"IFACE SYNC START (CONFIG LDP ON)",
|
||||
"IFACE SHUTDOWN",
|
||||
"N/A"
|
||||
};
|
||||
|
||||
const char * const ldp_sync_action_names[] = {
|
||||
"NOTHING",
|
||||
"IFACE SYNC START",
|
||||
"LDP START SYNC",
|
||||
"LDP COMPLETE SYNC",
|
||||
"CONFIG LDP OFF",
|
||||
"IFACE SHUTDOWN",
|
||||
"N/A"
|
||||
};
|
||||
|
||||
const char *
|
||||
ldp_sync_state_name(int state)
|
||||
{
|
||||
switch (state) {
|
||||
case LDP_SYNC_STA_NOT_ACH:
|
||||
return ("NOT ACHIEVED");
|
||||
case LDP_SYNC_STA_ACH:
|
||||
return ("ACHIEVED");
|
||||
default:
|
||||
return ("UNKNOWN");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
send_ldp_sync_state_update(char *name, int ifindex, int sync_start)
|
||||
{
|
||||
debug_evt_ldp_sync("%s: interface %s (%d), sync_start=%d",
|
||||
__func__, name, ifindex, sync_start);
|
||||
|
||||
struct ldp_igp_sync_if_state state;
|
||||
|
||||
state.ifindex = ifindex;
|
||||
state.sync_start = sync_start;
|
||||
|
||||
return ldpe_imsg_compose_parent(IMSG_LDP_SYNC_IF_STATE_UPDATE,
|
||||
getpid(), &state, sizeof(state));
|
||||
}
|
||||
|
||||
static int
|
||||
ldp_sync_act_iface_start_sync(struct iface *iface)
|
||||
{
|
||||
send_ldp_sync_state_update(iface->name, iface->ifindex, true);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
iface_wait_for_ldp_sync_timer(struct thread *thread)
|
||||
{
|
||||
struct iface *iface = THREAD_ARG(thread);
|
||||
|
||||
ldp_sync_fsm(iface, LDP_SYNC_EVT_LDP_SYNC_COMPLETE);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void start_wait_for_ldp_sync_timer(struct iface *iface)
|
||||
{
|
||||
if (iface->ldp_sync.wait_for_sync_timer)
|
||||
return;
|
||||
|
||||
THREAD_TIMER_OFF(iface->ldp_sync.wait_for_sync_timer);
|
||||
iface->ldp_sync.wait_for_sync_timer = NULL;
|
||||
thread_add_timer(master, iface_wait_for_ldp_sync_timer, iface,
|
||||
if_get_wait_for_sync_interval(),
|
||||
&iface->ldp_sync.wait_for_sync_timer);
|
||||
}
|
||||
|
||||
static void stop_wait_for_ldp_sync_timer(struct iface *iface)
|
||||
{
|
||||
THREAD_TIMER_OFF(iface->ldp_sync.wait_for_sync_timer);
|
||||
iface->ldp_sync.wait_for_sync_timer = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ldp_sync_act_ldp_start_sync(struct iface *iface)
|
||||
{
|
||||
start_wait_for_ldp_sync_timer(iface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ldp_sync_act_ldp_complete_sync(struct iface *iface)
|
||||
{
|
||||
send_ldp_sync_state_update(iface->name, iface->ifindex, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iface_to_oper_nbr_count(struct iface *iface, unsigned int type)
|
||||
{
|
||||
int oper_nbr_count = 0;
|
||||
struct adj *adj;
|
||||
|
||||
RB_FOREACH(adj, ia_adj_head, &iface->ipv4.adj_tree) {
|
||||
if (type == adj->source.type && adj->nbr &&
|
||||
adj->nbr->state == NBR_STA_OPER)
|
||||
oper_nbr_count++;
|
||||
}
|
||||
|
||||
RB_FOREACH(adj, ia_adj_head, &iface->ipv6.adj_tree) {
|
||||
if (type == adj->source.type && adj->nbr &&
|
||||
adj->nbr->state == NBR_STA_OPER)
|
||||
oper_nbr_count++;
|
||||
}
|
||||
|
||||
return oper_nbr_count;
|
||||
}
|
||||
|
||||
int
|
||||
ldp_sync_fsm_adj_event(struct adj *adj, enum ldp_sync_event event)
|
||||
{
|
||||
if (adj->source.type != HELLO_LINK)
|
||||
return -1;
|
||||
|
||||
struct iface *iface = adj->source.link.ia->iface;
|
||||
|
||||
if (!iface->operative)
|
||||
return 0;
|
||||
|
||||
if (event == LDP_SYNC_EVT_ADJ_NEW) {
|
||||
struct nbr *nbr = adj->nbr;
|
||||
if (nbr && nbr->state == NBR_STA_OPER) {
|
||||
event = LDP_SYNC_EVT_LDP_SYNC_START;
|
||||
}
|
||||
} else if (event == LDP_SYNC_EVT_ADJ_DEL) {
|
||||
/* Ignore if an operational neighbor exists.
|
||||
*/
|
||||
int oper_nbr_count = iface_to_oper_nbr_count(iface, HELLO_LINK);
|
||||
if (oper_nbr_count > 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug_evt_ldp_sync("%s: event %s, "
|
||||
"adj iface %s (%d) lsr-id %s "
|
||||
"source address %s transport address %s",
|
||||
__func__, ldp_sync_event_names[event],
|
||||
adj->source.link.ia->iface->name,
|
||||
adj->source.link.ia->iface->ifindex,
|
||||
inet_ntoa(adj->lsr_id),
|
||||
log_addr(adj_get_af(adj), &adj->source.link.src_addr),
|
||||
log_addr(adj_get_af(adj), &adj->trans_addr));
|
||||
|
||||
return ldp_sync_fsm(iface, event);
|
||||
}
|
||||
|
||||
int
|
||||
ldp_sync_fsm_nbr_event(struct nbr *nbr, enum ldp_sync_event event)
|
||||
{
|
||||
struct adj *adj;
|
||||
struct iface *iface = NULL;
|
||||
RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree) {
|
||||
if (HELLO_LINK != adj->source.type)
|
||||
continue;
|
||||
|
||||
iface = adj->source.link.ia->iface;
|
||||
|
||||
if (!iface || !iface->operative)
|
||||
continue;
|
||||
|
||||
int oper_nbr_count = iface_to_oper_nbr_count(iface, HELLO_LINK);
|
||||
|
||||
if (event == LDP_SYNC_EVT_SESSION_CLOSE && oper_nbr_count > 0)
|
||||
/* Ignore if an operational neighbor exists.
|
||||
*/
|
||||
continue;
|
||||
|
||||
debug_evt_ldp_sync("%s: event %s, iface %s, lsr-id %s",
|
||||
__func__, ldp_sync_event_names[event],
|
||||
iface->name, inet_ntoa(nbr->id));
|
||||
|
||||
ldp_sync_fsm(iface, event);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ldp_sync_fsm_state_req(struct ldp_igp_sync_if_state_req *state_req)
|
||||
{
|
||||
debug_evt_ldp_sync("%s: interface %s (%d) proto %s",
|
||||
__func__, state_req->name, state_req->ifindex,
|
||||
zebra_route_string(state_req->proto));
|
||||
|
||||
struct iface *iface = if_lookup_name(leconf, state_req->name);
|
||||
|
||||
if (!iface) {
|
||||
debug_evt_ldp_sync("%s: Warning: Ignoring LDP IGP SYNC "
|
||||
"interface state request for interface %s (%d). "
|
||||
"Interface does not exist in LDP.",
|
||||
__func__, state_req->name, state_req->ifindex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return send_ldp_sync_state_update(state_req->name,
|
||||
state_req->ifindex,
|
||||
(iface->ldp_sync.state != LDP_SYNC_STA_ACH));
|
||||
}
|
||||
|
||||
static int
|
||||
ldp_sync_fsm_init(struct iface *iface, int state)
|
||||
{
|
||||
int old_state = iface->ldp_sync.state;
|
||||
|
||||
iface->ldp_sync.state = state;
|
||||
stop_wait_for_ldp_sync_timer(iface);
|
||||
|
||||
send_ldp_sync_state_update(iface->name, iface->ifindex,
|
||||
(iface->ldp_sync.state != LDP_SYNC_STA_ACH));
|
||||
|
||||
if (old_state != iface->ldp_sync.state) {
|
||||
debug_evt_ldp_sync("%s: resulted in "
|
||||
"changing state for interface %s (%d) from %s to %s",
|
||||
__func__,
|
||||
iface->name, iface->ifindex,
|
||||
ldp_sync_state_name(old_state),
|
||||
ldp_sync_state_name(iface->ldp_sync.state));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ldp_sync_fsm(struct iface *iface, enum ldp_sync_event event)
|
||||
{
|
||||
int old_state = iface->ldp_sync.state;
|
||||
int new_state = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; ldp_sync_fsm_tbl[i].state != -1; i++)
|
||||
if ((ldp_sync_fsm_tbl[i].state & old_state) &&
|
||||
(ldp_sync_fsm_tbl[i].event == event)) {
|
||||
new_state = ldp_sync_fsm_tbl[i].new_state;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ldp_sync_fsm_tbl[i].state == -1) {
|
||||
/* event outside of the defined fsm, ignore it. */
|
||||
log_warnx("%s: interface %s, event %s not expected in "
|
||||
"state %s ", __func__, iface->name,
|
||||
ldp_sync_event_names[event],
|
||||
ldp_sync_state_name(old_state));
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (new_state != 0)
|
||||
iface->ldp_sync.state = new_state;
|
||||
|
||||
switch (ldp_sync_fsm_tbl[i].action) {
|
||||
case LDP_SYNC_ACT_IFACE_START_SYNC:
|
||||
ldp_sync_act_iface_start_sync(iface);
|
||||
break;
|
||||
case LDP_SYNC_ACT_LDP_START_SYNC:
|
||||
ldp_sync_act_ldp_start_sync(iface);
|
||||
break;
|
||||
case LDP_SYNC_ACT_LDP_COMPLETE_SYNC:
|
||||
ldp_sync_act_ldp_complete_sync(iface);
|
||||
break;
|
||||
case LDP_SYNC_ACT_CONFIG_LDP_OFF:
|
||||
ldp_sync_fsm_init(iface, LDP_SYNC_STA_NOT_ACH);
|
||||
break;
|
||||
case LDP_SYNC_ACT_IFACE_SHUTDOWN:
|
||||
ldp_sync_fsm_init(iface, iface->ldp_sync.state);
|
||||
break;
|
||||
case LDP_SYNC_ACT_NOTHING:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
if (old_state != iface->ldp_sync.state) {
|
||||
|
||||
debug_evt_ldp_sync("%s: event %s resulted in action %s "
|
||||
"for interface %s, changing state from %s to %s",
|
||||
__func__, ldp_sync_event_names[event],
|
||||
ldp_sync_action_names[ldp_sync_fsm_tbl[i].action],
|
||||
iface->name, ldp_sync_state_name(old_state),
|
||||
ldp_sync_state_name(iface->ldp_sync.state));
|
||||
|
||||
} else {
|
||||
debug_evt_ldp_sync("%s: event %s resulted in action %s "
|
||||
"for interface %s, remaining in state %s",
|
||||
__func__, ldp_sync_event_names[event],
|
||||
ldp_sync_action_names[ldp_sync_fsm_tbl[i].action],
|
||||
iface->name,
|
||||
ldp_sync_state_name(iface->ldp_sync.state));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ldp_sync_fsm_reset_all(void)
|
||||
{
|
||||
struct iface *iface;
|
||||
|
||||
RB_FOREACH(iface, iface_head, &leconf->iface_tree)
|
||||
ldp_sync_fsm(iface, LDP_SYNC_EVT_CONFIG_LDP_OFF);
|
||||
}
|
||||
|
||||
@ -51,6 +51,8 @@
|
||||
#define INIT_DELAY_TMR 15
|
||||
#define MAX_DELAY_TMR 120
|
||||
|
||||
#define DFLT_WAIT_FOR_SYNC 10
|
||||
|
||||
#define MIN_PWID_ID 1
|
||||
#define MAX_PWID_ID 0xffffffff
|
||||
|
||||
|
||||
@ -99,6 +99,11 @@ ldp_vty_debug(struct vty *vty, const char *negate, const char *type_str,
|
||||
DEBUG_ON(msg, LDP_DEBUG_MSG_SEND_ALL);
|
||||
}
|
||||
}
|
||||
} else if (strcmp(type_str, "sync") == 0) {
|
||||
if (negate)
|
||||
DEBUG_OFF(sync, LDP_DEBUG_SYNC);
|
||||
else
|
||||
DEBUG_ON(sync, LDP_DEBUG_SYNC);
|
||||
} else if (strcmp(type_str, "zebra") == 0) {
|
||||
if (negate)
|
||||
DEBUG_OFF(zebra, LDP_DEBUG_ZEBRA);
|
||||
@ -137,6 +142,8 @@ ldp_vty_show_debugging(struct vty *vty)
|
||||
" LDP detailed messages debugging is on (outbound)\n");
|
||||
else if (LDP_DEBUG(msg, LDP_DEBUG_MSG_SEND))
|
||||
vty_out (vty," LDP messages debugging is on (outbound)\n");
|
||||
if (LDP_DEBUG(sync, LDP_DEBUG_SYNC))
|
||||
vty_out (vty, " LDP sync debugging is on\n");
|
||||
if (LDP_DEBUG(zebra, LDP_DEBUG_ZEBRA))
|
||||
vty_out (vty, " LDP zebra debugging is on\n");
|
||||
vty_out (vty, "\n");
|
||||
@ -195,5 +202,10 @@ ldp_debug_config_write(struct vty *vty)
|
||||
write = 1;
|
||||
}
|
||||
|
||||
if (CONF_LDP_DEBUG(sync, LDP_DEBUG_SYNC)) {
|
||||
vty_out (vty, "debug mpls ldp sync\n");
|
||||
write = 1;
|
||||
}
|
||||
|
||||
return (write);
|
||||
}
|
||||
|
||||
@ -42,6 +42,10 @@ struct ldp_debug {
|
||||
|
||||
int zebra;
|
||||
#define LDP_DEBUG_ZEBRA 0x01
|
||||
|
||||
int sync;
|
||||
#define LDP_DEBUG_SYNC 0x01
|
||||
|
||||
};
|
||||
extern struct ldp_debug conf_ldp_debug;
|
||||
extern struct ldp_debug ldp_debug;
|
||||
@ -143,4 +147,10 @@ do { \
|
||||
log_debug("zebra[out]: " emsg, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define debug_evt_ldp_sync(emsg, ...) \
|
||||
do { \
|
||||
if (LDP_DEBUG(sync, LDP_DEBUG_SYNC)) \
|
||||
log_debug("sync: " emsg, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#endif /* _LDP_DEBUG_H_ */
|
||||
|
||||
@ -50,6 +50,7 @@ int ldp_vty_label_accept(struct vty *, const char *, const char *, const char *
|
||||
int ldp_vty_ttl_security(struct vty *, const char *);
|
||||
int ldp_vty_router_id(struct vty *, const char *, struct in_addr);
|
||||
int ldp_vty_ordered_control(struct vty *, const char *);
|
||||
int ldp_vty_wait_for_sync_interval(struct vty *, const char *, long);
|
||||
int ldp_vty_ds_cisco_interop(struct vty *, const char *);
|
||||
int ldp_vty_trans_pref_ipv4(struct vty *, const char *);
|
||||
int ldp_vty_neighbor_password(struct vty *, const char *, struct in_addr, const char *);
|
||||
@ -73,6 +74,7 @@ int ldp_vty_show_discovery(struct vty *, const char *, const char *, const char
|
||||
int ldp_vty_show_interface(struct vty *, const char *, const char *);
|
||||
int ldp_vty_show_capabilities(struct vty *, const char *);
|
||||
int ldp_vty_show_neighbor(struct vty *, const char *, int, const char *, const char *);
|
||||
int ldp_vty_show_ldp_sync(struct vty *, const char *);
|
||||
int ldp_vty_show_atom_binding(struct vty *, const char *, unsigned long,
|
||||
unsigned long, const char *);
|
||||
int ldp_vty_show_atom_vc(struct vty *, const char *, const char *,
|
||||
|
||||
@ -230,6 +230,17 @@ DEFPY (ldp_ordered_control,
|
||||
return (ldp_vty_ordered_control(vty, no));
|
||||
}
|
||||
|
||||
DEFPY (ldp_wait_for_sync,
|
||||
ldp_wait_for_sync_cmd,
|
||||
"[no] wait-for-sync (1-10000)$waitforsync",
|
||||
NO_STR
|
||||
"Time to wait for LDP-IGP Sync to complete label exchange\n"
|
||||
"Time (seconds)\n")
|
||||
{
|
||||
return (ldp_vty_wait_for_sync_interval(vty, no, waitforsync));
|
||||
|
||||
}
|
||||
|
||||
DEFPY (ldp_discovery_targeted_hello_accept,
|
||||
ldp_discovery_targeted_hello_accept_cmd,
|
||||
"[no] discovery targeted-hello accept [from <(1-199)|(1300-2699)|WORD>$from_acl]",
|
||||
@ -547,7 +558,7 @@ DEFPY (ldp_debug_mpls_ldp_discovery_hello,
|
||||
|
||||
DEFPY (ldp_debug_mpls_ldp_type,
|
||||
ldp_debug_mpls_ldp_type_cmd,
|
||||
"[no] debug mpls ldp <errors|event|labels|zebra>$type",
|
||||
"[no] debug mpls ldp <errors|event|labels|sync|zebra>$type",
|
||||
NO_STR
|
||||
"Debugging functions\n"
|
||||
"MPLS information\n"
|
||||
@ -555,6 +566,7 @@ DEFPY (ldp_debug_mpls_ldp_type,
|
||||
"Errors\n"
|
||||
"LDP event information\n"
|
||||
"LDP label allocation information\n"
|
||||
"LDP sync information\n"
|
||||
"LDP zebra information\n")
|
||||
{
|
||||
return (ldp_vty_debug(vty, no, type, NULL, NULL));
|
||||
@ -695,6 +707,18 @@ DEFPY (ldp_show_mpls_ldp_neighbor_capabilities,
|
||||
return (ldp_vty_show_neighbor(vty, lsr_id_str, 1, NULL, json));
|
||||
}
|
||||
|
||||
DEFPY (ldp_show_mpls_ldp_igp_sync,
|
||||
ldp_show_mpls_ldp_igp_sync_cmd,
|
||||
"show mpls ldp igp-sync [json]$json",
|
||||
"Show mpls ldp ldp-sync information\n"
|
||||
"MPLS information\n"
|
||||
"Label Distribution Protocol\n"
|
||||
"LDP-IGP Sync information\n"
|
||||
JSON_STR)
|
||||
{
|
||||
return (ldp_vty_show_ldp_sync(vty, json));
|
||||
}
|
||||
|
||||
DEFPY (ldp_show_l2vpn_atom_binding,
|
||||
ldp_show_l2vpn_atom_binding_cmd,
|
||||
"show l2vpn atom binding\
|
||||
@ -819,6 +843,7 @@ ldp_vty_init (void)
|
||||
install_element(LDP_NODE, &ldp_neighbor_ttl_security_cmd);
|
||||
install_element(LDP_NODE, &ldp_router_id_cmd);
|
||||
install_element(LDP_NODE, &ldp_ordered_control_cmd);
|
||||
install_element(LDP_NODE, &ldp_wait_for_sync_cmd);
|
||||
|
||||
install_element(LDP_IPV4_NODE, &ldp_discovery_link_holdtime_cmd);
|
||||
install_element(LDP_IPV4_NODE, &ldp_discovery_targeted_holdtime_cmd);
|
||||
@ -888,4 +913,5 @@ ldp_vty_init (void)
|
||||
install_element(VIEW_NODE, &ldp_show_l2vpn_atom_binding_cmd);
|
||||
install_element(VIEW_NODE, &ldp_show_l2vpn_atom_vc_cmd);
|
||||
install_element(VIEW_NODE, &ldp_show_debugging_mpls_ldp_cmd);
|
||||
install_element(VIEW_NODE, &ldp_show_mpls_ldp_igp_sync_cmd);
|
||||
}
|
||||
|
||||
@ -285,6 +285,11 @@ ldp_config_write(struct vty *vty)
|
||||
if (ldpd_conf->flags & F_LDPD_ORDERED_CONTROL)
|
||||
vty_out (vty, " ordered-control\n");
|
||||
|
||||
if (ldpd_conf->wait_for_sync_interval != DFLT_WAIT_FOR_SYNC &&
|
||||
ldpd_conf->wait_for_sync_interval != 0)
|
||||
vty_out (vty, " wait-for-sync %u\n",
|
||||
ldpd_conf->wait_for_sync_interval);
|
||||
|
||||
RB_FOREACH(nbrp, nbrp_head, &ldpd_conf->nbrp_tree) {
|
||||
if (nbrp->flags & F_NBRP_KEEPALIVE)
|
||||
vty_out (vty, " neighbor %s session holdtime %u\n",
|
||||
@ -477,7 +482,6 @@ int ldp_vty_disc_holdtime(struct vty *vty, const char *negate,
|
||||
struct iface *iface;
|
||||
struct iface_af *ia;
|
||||
int af;
|
||||
|
||||
switch (vty->node) {
|
||||
case LDP_NODE:
|
||||
if (negate) {
|
||||
@ -1014,6 +1018,24 @@ ldp_vty_ordered_control(struct vty *vty, const char *negate)
|
||||
return (CMD_SUCCESS);
|
||||
}
|
||||
|
||||
int ldp_vty_wait_for_sync_interval(struct vty *vty, const char *negate,
|
||||
long secs)
|
||||
{
|
||||
switch (vty->node) {
|
||||
case LDP_NODE:
|
||||
if (negate)
|
||||
vty_conf->wait_for_sync_interval = DFLT_WAIT_FOR_SYNC;
|
||||
else
|
||||
vty_conf->wait_for_sync_interval = secs;
|
||||
|
||||
ldp_config_apply(vty, vty_conf);
|
||||
break;
|
||||
default:
|
||||
fatalx("ldp_vty_wait_for_sync_interval: unexpected node");
|
||||
}
|
||||
return (CMD_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_ds_cisco_interop(struct vty *vty, const char * negate)
|
||||
{
|
||||
|
||||
@ -37,7 +37,8 @@ enum show_command {
|
||||
SHOW_NBR,
|
||||
SHOW_LIB,
|
||||
SHOW_L2VPN_PW,
|
||||
SHOW_L2VPN_BINDING
|
||||
SHOW_L2VPN_BINDING,
|
||||
SHOW_LDP_SYNC
|
||||
};
|
||||
|
||||
struct show_params {
|
||||
@ -86,6 +87,10 @@ static void show_discovery_detail_adj_json(json_object *,
|
||||
struct ctl_adj *);
|
||||
static int show_discovery_detail_msg_json(struct imsg *,
|
||||
struct show_params *, json_object *);
|
||||
static int show_ldp_sync_msg(struct vty *, struct imsg *,
|
||||
struct show_params *);
|
||||
static int show_ldp_sync_msg_json(struct imsg *,
|
||||
struct show_params *, json_object *);
|
||||
|
||||
static int show_nbr_msg(struct vty *, struct imsg *,
|
||||
struct show_params *);
|
||||
@ -122,7 +127,6 @@ static int show_l2vpn_pw_msg(struct vty *, struct imsg *,
|
||||
struct show_params *);
|
||||
static int show_l2vpn_pw_msg_json(struct imsg *,
|
||||
struct show_params *, json_object *);
|
||||
static int ldp_vty_connect(struct imsgbuf *);
|
||||
static int ldp_vty_dispatch_msg(struct vty *, struct imsg *,
|
||||
enum show_command, struct show_params *,
|
||||
json_object *);
|
||||
@ -206,6 +210,87 @@ show_interface_msg_json(struct imsg *imsg, struct show_params *params,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
show_ldp_sync_msg(struct vty *vty, struct imsg *imsg,
|
||||
struct show_params *params)
|
||||
{
|
||||
struct ctl_ldp_sync *iface;
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case IMSG_CTL_SHOW_LDP_SYNC:
|
||||
iface = imsg->data;
|
||||
|
||||
vty_out (vty, "%s:\n", iface->name);
|
||||
if (iface->in_sync)
|
||||
vty_out (vty, " Status: initial label exchange complete\n");
|
||||
else
|
||||
vty_out (vty, " Status: label exchange not complete\n");
|
||||
|
||||
if (iface->timer_running) {
|
||||
vty_out (vty, " Wait time: %d seconds (%d seconds left)\n",
|
||||
iface->wait_time, iface->wait_time_remaining);
|
||||
vty_out (vty, " Timer is running\n");
|
||||
} else {
|
||||
vty_out (vty, " Wait time: %d seconds\n",
|
||||
iface->wait_time);
|
||||
vty_out (vty, " Timer is not running\n");
|
||||
}
|
||||
|
||||
if (iface->peer_ldp_id.s_addr)
|
||||
vty_out (vty, " Peer LDP Identifier: %s:0\n",
|
||||
inet_ntoa(iface->peer_ldp_id));
|
||||
|
||||
break;
|
||||
case IMSG_CTL_END:
|
||||
return (1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
show_ldp_sync_msg_json(struct imsg *imsg, struct show_params *params,
|
||||
json_object *json)
|
||||
{
|
||||
struct ctl_ldp_sync *iface;
|
||||
json_object *json_iface;
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case IMSG_CTL_SHOW_LDP_SYNC:
|
||||
iface = imsg->data;
|
||||
|
||||
json_iface = json_object_new_object();
|
||||
json_object_string_add(json_iface, "state",
|
||||
iface->in_sync
|
||||
? "labelExchangeComplete"
|
||||
: "labelExchangeNotComplete");
|
||||
json_object_int_add(json_iface, "waitTime",
|
||||
iface->wait_time);
|
||||
json_object_int_add(json_iface, "waitTimeRemaining",
|
||||
iface->wait_time_remaining);
|
||||
|
||||
if (iface->timer_running)
|
||||
json_object_boolean_true_add(json_iface, "timerRunning");
|
||||
else
|
||||
json_object_boolean_false_add(json_iface, "timerRunning");
|
||||
|
||||
json_object_string_add(json_iface, "peerLdpId",
|
||||
iface->peer_ldp_id.s_addr ?
|
||||
inet_ntoa(iface->peer_ldp_id) : "");
|
||||
|
||||
json_object_object_add(json, iface->name, json_iface);
|
||||
break;
|
||||
case IMSG_CTL_END:
|
||||
return (1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
show_discovery_msg(struct vty *vty, struct imsg *imsg,
|
||||
struct show_params *params)
|
||||
@ -1436,6 +1521,20 @@ ldp_vty_dispatch_iface(struct vty *vty, struct imsg *imsg,
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
ldp_vty_dispatch_ldp_sync(struct vty *vty, struct imsg *imsg,
|
||||
struct show_params *params, json_object *json)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (params->json)
|
||||
ret = show_ldp_sync_msg_json(imsg, params, json);
|
||||
else
|
||||
ret = show_ldp_sync_msg(vty, imsg, params);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
ldp_vty_dispatch_disc(struct vty *vty, struct imsg *imsg,
|
||||
struct show_params *params, json_object *json)
|
||||
@ -1684,6 +1783,8 @@ ldp_vty_dispatch_msg(struct vty *vty, struct imsg *imsg, enum show_command cmd,
|
||||
case SHOW_L2VPN_BINDING:
|
||||
return (ldp_vty_dispatch_l2vpn_binding(vty, imsg, params,
|
||||
json));
|
||||
case SHOW_LDP_SYNC:
|
||||
return (ldp_vty_dispatch_ldp_sync(vty, imsg, params, json));
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
@ -1945,6 +2046,22 @@ ldp_vty_show_neighbor(struct vty *vty, const char *lsr_id, int capabilities,
|
||||
return (ldp_vty_dispatch(vty, &ibuf, SHOW_NBR, ¶ms));
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_show_ldp_sync(struct vty *vty, const char *json)
|
||||
{
|
||||
struct imsgbuf ibuf;
|
||||
struct show_params params;
|
||||
|
||||
if (ldp_vty_connect(&ibuf) < 0)
|
||||
return (CMD_WARNING);
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.json = (json) ? 1 : 0;
|
||||
|
||||
imsg_compose(&ibuf, IMSG_CTL_SHOW_LDP_SYNC, 0, 0, -1, NULL, 0);
|
||||
return (ldp_vty_dispatch(vty, &ibuf, SHOW_LDP_SYNC, ¶ms));
|
||||
}
|
||||
|
||||
int
|
||||
ldp_vty_show_atom_binding(struct vty *vty, const char *peer,
|
||||
unsigned long local_label, unsigned long remote_label, const char *json)
|
||||
|
||||
110
ldpd/ldp_zebra.c
110
ldpd/ldp_zebra.c
@ -31,6 +31,7 @@
|
||||
#include "ldpd.h"
|
||||
#include "ldpe.h"
|
||||
#include "lde.h"
|
||||
#include "ldp_sync.h"
|
||||
#include "log.h"
|
||||
#include "ldp_debug.h"
|
||||
|
||||
@ -46,6 +47,14 @@ static int ldp_zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS);
|
||||
static void ldp_zebra_connected(struct zclient *);
|
||||
static void ldp_zebra_filter_update(struct access_list *access);
|
||||
|
||||
static void ldp_zebra_opaque_register(void);
|
||||
static void ldp_zebra_opaque_unregister(void);
|
||||
static int ldp_sync_zebra_send_announce(void);
|
||||
static int ldp_zebra_opaque_msg_handler(ZAPI_CALLBACK_ARGS);
|
||||
static void ldp_sync_zebra_start_hello_timer(void);
|
||||
static int ldp_sync_zebra_hello(struct thread *thread);
|
||||
static void ldp_sync_zebra_init(void);
|
||||
|
||||
static struct zclient *zclient;
|
||||
|
||||
static void
|
||||
@ -103,6 +112,95 @@ pw2zpw(struct l2vpn_pw *pw, struct zapi_pw *zpw)
|
||||
sizeof(zpw->data.ldp.vpn_name));
|
||||
}
|
||||
|
||||
static void
|
||||
ldp_zebra_opaque_register(void)
|
||||
{
|
||||
zclient_register_opaque(zclient, LDP_IGP_SYNC_IF_STATE_REQUEST);
|
||||
}
|
||||
|
||||
static void
|
||||
ldp_zebra_opaque_unregister(void)
|
||||
{
|
||||
zclient_unregister_opaque(zclient, LDP_IGP_SYNC_IF_STATE_REQUEST);
|
||||
}
|
||||
|
||||
int
|
||||
ldp_sync_zebra_send_state_update(struct ldp_igp_sync_if_state *state)
|
||||
{
|
||||
return zclient_send_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE,
|
||||
(const uint8_t *) state, sizeof(*state));
|
||||
}
|
||||
|
||||
static int
|
||||
ldp_sync_zebra_send_announce(void)
|
||||
{
|
||||
struct ldp_igp_sync_announce announce;
|
||||
announce.proto = ZEBRA_ROUTE_LDP;
|
||||
|
||||
return zclient_send_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE,
|
||||
(const uint8_t *) &announce, sizeof(announce));
|
||||
}
|
||||
|
||||
static int
|
||||
ldp_zebra_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_opaque_msg info;
|
||||
struct ldp_igp_sync_if_state_req state_req;
|
||||
|
||||
s = zclient->ibuf;
|
||||
|
||||
if (zclient_opaque_decode(s, &info) != 0)
|
||||
return -1;
|
||||
|
||||
switch (info.type) {
|
||||
case LDP_IGP_SYNC_IF_STATE_REQUEST:
|
||||
STREAM_GET(&state_req, s, sizeof(state_req));
|
||||
main_imsg_compose_ldpe(IMSG_LDP_SYNC_IF_STATE_REQUEST, 0, &state_req,
|
||||
sizeof(state_req));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
stream_failure:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ldp_sync_zebra_start_hello_timer(void)
|
||||
{
|
||||
thread_add_timer_msec(master, ldp_sync_zebra_hello, NULL, 250, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
ldp_sync_zebra_hello(struct thread *thread)
|
||||
{
|
||||
static unsigned int sequence = 0;
|
||||
struct ldp_igp_sync_hello hello;
|
||||
|
||||
sequence++;
|
||||
|
||||
hello.proto = ZEBRA_ROUTE_LDP;
|
||||
hello.sequence = sequence;
|
||||
|
||||
zclient_send_opaque(zclient, LDP_IGP_SYNC_HELLO_UPDATE,
|
||||
(const uint8_t *) &hello, sizeof(hello));
|
||||
|
||||
ldp_sync_zebra_start_hello_timer();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ldp_sync_zebra_init(void)
|
||||
{
|
||||
ldp_sync_zebra_send_announce();
|
||||
|
||||
ldp_sync_zebra_start_hello_timer();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr)
|
||||
{
|
||||
@ -299,7 +397,7 @@ ldp_ifp_destroy(struct interface *ifp)
|
||||
}
|
||||
|
||||
static int
|
||||
ldp_interface_status_change_helper(struct interface *ifp)
|
||||
ldp_interface_status_change(struct interface *ifp)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct connected *ifc;
|
||||
@ -330,12 +428,12 @@ ldp_interface_status_change_helper(struct interface *ifp)
|
||||
|
||||
static int ldp_ifp_up(struct interface *ifp)
|
||||
{
|
||||
return ldp_interface_status_change_helper(ifp);
|
||||
return ldp_interface_status_change(ifp);
|
||||
}
|
||||
|
||||
static int ldp_ifp_down(struct interface *ifp)
|
||||
{
|
||||
return ldp_interface_status_change_helper(ifp);
|
||||
return ldp_interface_status_change(ifp);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -525,6 +623,10 @@ ldp_zebra_connected(struct zclient *zclient)
|
||||
ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
|
||||
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6,
|
||||
ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
|
||||
|
||||
ldp_zebra_opaque_register();
|
||||
|
||||
ldp_sync_zebra_init();
|
||||
}
|
||||
|
||||
static void
|
||||
@ -563,6 +665,7 @@ ldp_zebra_init(struct thread_master *master)
|
||||
zclient->redistribute_route_add = ldp_zebra_read_route;
|
||||
zclient->redistribute_route_del = ldp_zebra_read_route;
|
||||
zclient->pw_status_update = ldp_zebra_read_pw_status_update;
|
||||
zclient->opaque_msg_handler = ldp_zebra_opaque_msg_handler;
|
||||
|
||||
/* Access list initialize. */
|
||||
access_list_add_hook(ldp_zebra_filter_update);
|
||||
@ -572,6 +675,7 @@ ldp_zebra_init(struct thread_master *master)
|
||||
void
|
||||
ldp_zebra_destroy(void)
|
||||
{
|
||||
ldp_zebra_opaque_unregister();
|
||||
zclient_stop(zclient);
|
||||
zclient_free(zclient);
|
||||
zclient = NULL;
|
||||
|
||||
17
ldpd/ldpd.c
17
ldpd/ldpd.c
@ -586,6 +586,13 @@ main_dispatch_ldpe(struct thread *thread)
|
||||
fatalx("IMSG_ACL_CHECK imsg with wrong len");
|
||||
ldp_acl_reply(iev, (struct acl_check *)imsg.data);
|
||||
break;
|
||||
case IMSG_LDP_SYNC_IF_STATE_UPDATE:
|
||||
if (imsg.hdr.len != IMSG_HEADER_SIZE +
|
||||
sizeof(struct ldp_igp_sync_if_state))
|
||||
fatalx("IMSG_LDP_SYNC_IF_STATE_UPDATE imsg with wrong len");
|
||||
|
||||
ldp_sync_zebra_send_state_update((struct ldp_igp_sync_if_state *)imsg.data);
|
||||
break;
|
||||
default:
|
||||
log_debug("%s: error handling imsg %d", __func__,
|
||||
imsg.hdr.type);
|
||||
@ -1148,6 +1155,7 @@ ldp_config_reset_main(struct ldpd_conf *conf)
|
||||
conf->lhello_interval = DEFAULT_HELLO_INTERVAL;
|
||||
conf->thello_holdtime = TARGETED_DFLT_HOLDTIME;
|
||||
conf->thello_interval = DEFAULT_HELLO_INTERVAL;
|
||||
conf->wait_for_sync_interval = DFLT_WAIT_FOR_SYNC;
|
||||
conf->trans_pref = DUAL_STACK_LDPOV6;
|
||||
conf->flags = 0;
|
||||
}
|
||||
@ -1278,6 +1286,14 @@ merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
||||
static void
|
||||
merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
||||
{
|
||||
/* Removing global LDP config requires resetting LDP IGP Sync FSM */
|
||||
if ((conf->flags & F_LDPD_ENABLED) &&
|
||||
(!(xconf->flags & F_LDPD_ENABLED)))
|
||||
{
|
||||
if (ldpd_process == PROC_LDP_ENGINE)
|
||||
ldp_sync_fsm_reset_all();
|
||||
}
|
||||
|
||||
/* change of router-id requires resetting all neighborships */
|
||||
if (conf->rtr_id.s_addr != xconf->rtr_id.s_addr) {
|
||||
if (ldpd_process == PROC_LDP_ENGINE) {
|
||||
@ -1303,6 +1319,7 @@ merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
||||
conf->lhello_interval = xconf->lhello_interval;
|
||||
conf->thello_holdtime = xconf->thello_holdtime;
|
||||
conf->thello_interval = xconf->thello_interval;
|
||||
conf->wait_for_sync_interval = xconf->wait_for_sync_interval;
|
||||
|
||||
if (conf->trans_pref != xconf->trans_pref) {
|
||||
if (ldpd_process == PROC_LDP_ENGINE)
|
||||
|
||||
52
ldpd/ldpd.h
52
ldpd/ldpd.h
@ -34,6 +34,7 @@
|
||||
#include "zclient.h"
|
||||
|
||||
#include "ldp.h"
|
||||
#include "lib/ldp_sync.h"
|
||||
|
||||
#define CONF_FILE "/etc/ldpd.conf"
|
||||
#define LDPD_USER "_ldpd"
|
||||
@ -93,6 +94,7 @@ enum imsg_type {
|
||||
IMSG_CTL_SHOW_LIB_END,
|
||||
IMSG_CTL_SHOW_L2VPN_PW,
|
||||
IMSG_CTL_SHOW_L2VPN_BINDING,
|
||||
IMSG_CTL_SHOW_LDP_SYNC,
|
||||
IMSG_CTL_CLEAR_NBR,
|
||||
IMSG_CTL_FIB_COUPLE,
|
||||
IMSG_CTL_FIB_DECOUPLE,
|
||||
@ -153,7 +155,9 @@ enum imsg_type {
|
||||
IMSG_INIT,
|
||||
IMSG_PW_UPDATE,
|
||||
IMSG_FILTER_UPDATE,
|
||||
IMSG_NBR_SHUTDOWN
|
||||
IMSG_NBR_SHUTDOWN,
|
||||
IMSG_LDP_SYNC_IF_STATE_REQUEST,
|
||||
IMSG_LDP_SYNC_IF_STATE_UPDATE
|
||||
};
|
||||
|
||||
struct ldpd_init {
|
||||
@ -227,6 +231,34 @@ enum nbr_action {
|
||||
NBR_ACT_CLOSE_SESSION
|
||||
};
|
||||
|
||||
/* LDP IGP Sync states */
|
||||
#define LDP_SYNC_STA_UNKNOWN 0x0000
|
||||
#define LDP_SYNC_STA_NOT_ACH 0x0001
|
||||
#define LDP_SYNC_STA_ACH 0x0002
|
||||
|
||||
/* LDP IGP Sync events */
|
||||
enum ldp_sync_event {
|
||||
LDP_SYNC_EVT_NOTHING,
|
||||
LDP_SYNC_EVT_LDP_SYNC_START,
|
||||
LDP_SYNC_EVT_LDP_SYNC_COMPLETE,
|
||||
LDP_SYNC_EVT_CONFIG_LDP_OFF,
|
||||
LDP_SYNC_EVT_ADJ_DEL,
|
||||
LDP_SYNC_EVT_ADJ_NEW,
|
||||
LDP_SYNC_EVT_SESSION_CLOSE,
|
||||
LDP_SYNC_EVT_CONFIG_LDP_ON,
|
||||
LDP_SYNC_EVT_IFACE_SHUTDOWN
|
||||
};
|
||||
|
||||
/* LDP IGP Sync actions */
|
||||
enum ldp_sync_action {
|
||||
LDP_SYNC_ACT_NOTHING,
|
||||
LDP_SYNC_ACT_IFACE_START_SYNC,
|
||||
LDP_SYNC_ACT_LDP_START_SYNC,
|
||||
LDP_SYNC_ACT_LDP_COMPLETE_SYNC,
|
||||
LDP_SYNC_ACT_CONFIG_LDP_OFF,
|
||||
LDP_SYNC_ACT_IFACE_SHUTDOWN
|
||||
};
|
||||
|
||||
/* forward declarations */
|
||||
RB_HEAD(global_adj_head, adj);
|
||||
RB_HEAD(nbr_adj_head, adj);
|
||||
@ -310,6 +342,11 @@ struct iface_af {
|
||||
uint16_t hello_interval;
|
||||
};
|
||||
|
||||
struct iface_ldp_sync {
|
||||
int state;
|
||||
struct thread *wait_for_sync_timer;
|
||||
};
|
||||
|
||||
struct iface {
|
||||
RB_ENTRY(iface) entry;
|
||||
char name[IF_NAMESIZE];
|
||||
@ -320,6 +357,7 @@ struct iface {
|
||||
int operative;
|
||||
struct iface_af ipv4;
|
||||
struct iface_af ipv6;
|
||||
struct iface_ldp_sync ldp_sync;
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
RB_HEAD(iface_head, iface);
|
||||
@ -518,6 +556,7 @@ struct ldpd_conf {
|
||||
uint16_t thello_holdtime;
|
||||
uint16_t thello_interval;
|
||||
uint16_t trans_pref;
|
||||
uint16_t wait_for_sync_interval;
|
||||
int flags;
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
@ -672,6 +711,16 @@ struct ctl_pw {
|
||||
uint8_t reason;
|
||||
};
|
||||
|
||||
struct ctl_ldp_sync {
|
||||
char name[IF_NAMESIZE];
|
||||
ifindex_t ifindex;
|
||||
bool in_sync;
|
||||
bool timer_running;
|
||||
uint16_t wait_time;
|
||||
uint16_t wait_time_remaining;
|
||||
struct in_addr peer_ldp_id;
|
||||
};
|
||||
|
||||
extern struct ldpd_conf *ldpd_conf, *vty_conf;
|
||||
extern struct ldpd_global global;
|
||||
extern struct ldpd_init init;
|
||||
@ -825,6 +874,7 @@ extern char ctl_sock_path[MAXPATHLEN];
|
||||
/* ldp_zebra.c */
|
||||
void ldp_zebra_init(struct thread_master *);
|
||||
void ldp_zebra_destroy(void);
|
||||
int ldp_sync_zebra_send_state_update(struct ldp_igp_sync_if_state *);
|
||||
|
||||
/* compatibility */
|
||||
#ifndef __OpenBSD__
|
||||
|
||||
24
ldpd/ldpe.c
24
ldpd/ldpe.c
@ -297,6 +297,7 @@ ldpe_dispatch_main(struct thread *thread)
|
||||
#endif
|
||||
int n, shut = 0;
|
||||
struct ldp_access *laccess;
|
||||
struct ldp_igp_sync_if_state_req *ldp_sync_if_state_req;
|
||||
|
||||
iev->ev_read = NULL;
|
||||
|
||||
@ -559,6 +560,15 @@ ldpe_dispatch_main(struct thread *thread)
|
||||
ldpe_check_filter_af(AF_INET6, &leconf->ipv6,
|
||||
laccess->name);
|
||||
break;
|
||||
case IMSG_LDP_SYNC_IF_STATE_REQUEST:
|
||||
if (imsg.hdr.len != IMSG_HEADER_SIZE +
|
||||
sizeof(struct ldp_igp_sync_if_state_req)) {
|
||||
log_warnx("%s: wrong imsg len", __func__);
|
||||
break;
|
||||
}
|
||||
ldp_sync_if_state_req = imsg.data;
|
||||
ldp_sync_fsm_state_req(ldp_sync_if_state_req);
|
||||
break;
|
||||
default:
|
||||
log_debug("ldpe_dispatch_main: error handling imsg %d",
|
||||
imsg.hdr.type);
|
||||
@ -974,6 +984,20 @@ ldpe_nbr_ctl(struct ctl_conn *c)
|
||||
imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
|
||||
}
|
||||
|
||||
void
|
||||
ldpe_ldp_sync_ctl(struct ctl_conn *c)
|
||||
{
|
||||
struct iface *iface;
|
||||
struct ctl_ldp_sync *ictl;
|
||||
|
||||
RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
|
||||
ictl = ldp_sync_to_ctl(iface);
|
||||
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_LDP_SYNC,
|
||||
0, 0, -1, ictl, sizeof(struct ctl_ldp_sync));
|
||||
}
|
||||
imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
|
||||
}
|
||||
|
||||
void
|
||||
mapping_list_add(struct mapping_head *mh, struct map *map)
|
||||
{
|
||||
|
||||
11
ldpd/ldpe.h
11
ldpd/ldpe.h
@ -28,6 +28,7 @@
|
||||
#endif
|
||||
|
||||
#include "ldpd.h"
|
||||
#include "lib/ldp_sync.h"
|
||||
|
||||
#define min(x,y) ((x) <= (y) ? (x) : (y))
|
||||
#define max(x,y) ((x) > (y) ? (x) : (y))
|
||||
@ -212,6 +213,7 @@ void ldpe_iface_ctl(struct ctl_conn *c, ifindex_t ifidx);
|
||||
void ldpe_adj_ctl(struct ctl_conn *);
|
||||
void ldpe_adj_detail_ctl(struct ctl_conn *);
|
||||
void ldpe_nbr_ctl(struct ctl_conn *);
|
||||
void ldpe_ldp_sync_ctl(struct ctl_conn *);
|
||||
void mapping_list_add(struct mapping_head *, struct map *);
|
||||
void mapping_list_clr(struct mapping_head *);
|
||||
|
||||
@ -229,8 +231,17 @@ void ldp_if_update(struct iface *, int);
|
||||
void if_update_all(int);
|
||||
uint16_t if_get_hello_holdtime(struct iface_af *);
|
||||
uint16_t if_get_hello_interval(struct iface_af *);
|
||||
uint16_t if_get_wait_for_sync_interval(void);
|
||||
struct ctl_iface *if_to_ctl(struct iface_af *);
|
||||
in_addr_t if_get_ipv4_addr(struct iface *);
|
||||
int ldp_sync_fsm_adj_event(struct adj *, enum ldp_sync_event);
|
||||
int ldp_sync_fsm_nbr_event(struct nbr *, enum ldp_sync_event);
|
||||
int ldp_sync_fsm_state_req(struct ldp_igp_sync_if_state_req *);
|
||||
int ldp_sync_fsm(struct iface *, enum ldp_sync_event);
|
||||
void ldp_sync_fsm_reset_all(void);
|
||||
const char *ldp_sync_state_name(int);
|
||||
const char *ldp_sync_event_name(int);
|
||||
struct ctl_ldp_sync *ldp_sync_to_ctl(struct iface *);
|
||||
|
||||
/* adjacency.c */
|
||||
struct adj *adj_new(struct in_addr, struct hello_source *,
|
||||
|
||||
@ -764,6 +764,8 @@ nbr_act_session_operational(struct nbr *nbr)
|
||||
/* this is necessary to avoid ipc synchronization issues */
|
||||
nbr_update_peerid(nbr);
|
||||
|
||||
ldp_sync_fsm_nbr_event(nbr, LDP_SYNC_EVT_LDP_SYNC_START);
|
||||
|
||||
memset(&lde_nbr, 0, sizeof(lde_nbr));
|
||||
lde_nbr.id = nbr->id;
|
||||
lde_nbr.v4_enabled = nbr->v4_enabled;
|
||||
|
||||
@ -683,6 +683,8 @@ session_close(struct nbr *nbr)
|
||||
log_debug("%s: closing session with lsr-id %s", __func__,
|
||||
inet_ntoa(nbr->id));
|
||||
|
||||
ldp_sync_fsm_nbr_event(nbr, LDP_SYNC_EVT_SESSION_CLOSE);
|
||||
|
||||
tcp_close(nbr->tcp);
|
||||
nbr_stop_ktimer(nbr);
|
||||
nbr_stop_ktimeout(nbr);
|
||||
|
||||
@ -421,6 +421,11 @@ struct cmd_node {
|
||||
|
||||
#define CMD_VNI_RANGE "(1-16777215)"
|
||||
#define CONF_BACKUP_EXT ".sav"
|
||||
#define MPLS_LDP_SYNC_STR "Enable MPLS LDP-SYNC\n"
|
||||
#define NO_MPLS_LDP_SYNC_STR "Disable MPLS LDP-SYNC\n"
|
||||
#define MPLS_LDP_SYNC_HOLDDOWN_STR \
|
||||
"Time to wait for LDP-SYNC to occur before restoring if cost\n"
|
||||
#define NO_MPLS_LDP_SYNC_HOLDDOWN_STR "holddown timer disable\n"
|
||||
|
||||
/* Command warnings. */
|
||||
#define NO_PASSWD_CMD_WARNING \
|
||||
|
||||
93
lib/ldp_sync.c
Normal file
93
lib/ldp_sync.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* ldp_sync.c: LDP-SYNC handling routines
|
||||
* 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 General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "command.h"
|
||||
#include "memory.h"
|
||||
#include "prefix.h"
|
||||
#include "log.h"
|
||||
#include "thread.h"
|
||||
#include "stream.h"
|
||||
#include "zclient.h"
|
||||
#include "table.h"
|
||||
#include "vty.h"
|
||||
#include "ldp_sync.h"
|
||||
|
||||
/* Library code */
|
||||
DEFINE_MTYPE_STATIC(LIB, LDP_SYNC_INFO, "LDP SYNC info")
|
||||
|
||||
/*
|
||||
* ldp_sync_info_create - Allocate the LDP_SYNC information
|
||||
*/
|
||||
struct ldp_sync_info *ldp_sync_info_create(void)
|
||||
{
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
|
||||
ldp_sync_info = XCALLOC(MTYPE_LDP_SYNC_INFO,
|
||||
sizeof(struct ldp_sync_info));
|
||||
assert(ldp_sync_info);
|
||||
|
||||
ldp_sync_info->flags = 0;
|
||||
ldp_sync_info->enabled = LDP_IGP_SYNC_DEFAULT;
|
||||
ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
|
||||
ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
|
||||
ldp_sync_info->t_holddown = NULL;
|
||||
return ldp_sync_info;
|
||||
}
|
||||
|
||||
/*
|
||||
* ldp_sync_info_free - Free the LDP_SYNC information.
|
||||
*/
|
||||
void ldp_sync_info_free(struct ldp_sync_info **ldp_sync_info)
|
||||
{
|
||||
if (*ldp_sync_info)
|
||||
XFREE(MTYPE_LDP_SYNC_INFO, *ldp_sync_info);
|
||||
}
|
||||
|
||||
bool ldp_sync_if_is_enabled(struct ldp_sync_info *ldp_sync_info)
|
||||
{
|
||||
/* return true if LDP-SYNC is configured on this interface */
|
||||
if (ldp_sync_info &&
|
||||
ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED &&
|
||||
ldp_sync_info->state == LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ldp_sync_if_down(struct ldp_sync_info *ldp_sync_info)
|
||||
{
|
||||
/* Stop LDP-SYNC on this interface:
|
||||
* if holddown timer is running stop it
|
||||
* update state
|
||||
*/
|
||||
if (ldp_sync_info && ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED) {
|
||||
if (ldp_sync_info->t_holddown != NULL) {
|
||||
THREAD_TIMER_OFF(ldp_sync_info->t_holddown);
|
||||
ldp_sync_info->t_holddown = NULL;
|
||||
}
|
||||
if (ldp_sync_info->state == LDP_IGP_SYNC_STATE_REQUIRED_UP)
|
||||
ldp_sync_info->state =
|
||||
LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
91
lib/ldp_sync.h
Normal file
91
lib/ldp_sync.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Defines and structures common to LDP-Sync for OSPFv2 and OSPFv3 and ISIS
|
||||
* 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 General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _LIBLDPSYNC_H
|
||||
#define _LIBLDPSYNC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* LDP-IGP Sync values */
|
||||
#define LDP_SYNC_FLAG_ENABLE (1 << 0) /* LDP-SYNC enabled */
|
||||
#define LDP_SYNC_FLAG_HOLDDOWN (1 << 1) /* Holddown timer enabled */
|
||||
#define LDP_SYNC_FLAG_IF_CONFIG (1 << 2) /* LDP-SYNC enabled on interface */
|
||||
#define LDP_SYNC_FLAG_SET_METRIC (1 << 3) /* Metric has been set on ISIS intf */
|
||||
|
||||
#define LDP_IGP_SYNC_DEFAULT 0
|
||||
#define LDP_IGP_SYNC_ENABLED 1
|
||||
|
||||
#define LDP_IGP_SYNC_STATE_NOT_REQUIRED 0
|
||||
#define LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP 1
|
||||
#define LDP_IGP_SYNC_STATE_REQUIRED_UP 2
|
||||
|
||||
#define LDP_IGP_SYNC_HOLDDOWN_DEFAULT 0
|
||||
|
||||
#define LDP_IGP_SYNC_HELLO_TIMEOUT 1
|
||||
|
||||
/* LDP-IGP Sync structures */
|
||||
struct ldp_sync_info_cmd {
|
||||
uint16_t flags;
|
||||
uint16_t holddown; /* timer value */
|
||||
uint32_t sequence; /* hello sequence number */
|
||||
struct thread *t_hello; /* hello timer for detecting LDP going down */
|
||||
};
|
||||
|
||||
struct ldp_sync_info {
|
||||
uint16_t flags; /* indicate if set on interface or globally */
|
||||
uint8_t enabled; /* enabled */
|
||||
uint8_t state; /* running state */
|
||||
uint16_t holddown; /* timer value */
|
||||
struct thread *t_holddown; /* holddown timer*/
|
||||
uint32_t metric[2]; /* isis interface metric */
|
||||
};
|
||||
|
||||
/* Prototypes. */
|
||||
extern struct ldp_sync_info *ldp_sync_info_create(void);
|
||||
extern bool ldp_sync_if_is_enabled(struct ldp_sync_info *ldp_sync_info);
|
||||
extern bool ldp_sync_if_down(struct ldp_sync_info *ldp_sync_info);
|
||||
extern void ldp_sync_info_free(struct ldp_sync_info **ldp_sync_info);
|
||||
|
||||
struct ldp_igp_sync_announce {
|
||||
int proto;
|
||||
};
|
||||
|
||||
struct ldp_igp_sync_if_state {
|
||||
ifindex_t ifindex;
|
||||
bool sync_start;
|
||||
};
|
||||
|
||||
struct ldp_igp_sync_if_state_req {
|
||||
int proto;
|
||||
ifindex_t ifindex;
|
||||
char name[INTERFACE_NAMSIZ];
|
||||
};
|
||||
|
||||
struct ldp_igp_sync_hello {
|
||||
int proto;
|
||||
unsigned int sequence;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBLDPSYNC_H */
|
||||
@ -42,6 +42,7 @@ lib_libfrr_la_SOURCES = \
|
||||
lib/jhash.c \
|
||||
lib/json.c \
|
||||
lib/keychain.c \
|
||||
lib/ldp_sync.c \
|
||||
lib/lib_errors.c \
|
||||
lib/lib_vty.c \
|
||||
lib/libfrr.c \
|
||||
@ -198,6 +199,7 @@ pkginclude_HEADERS += \
|
||||
lib/jhash.h \
|
||||
lib/json.h \
|
||||
lib/keychain.h \
|
||||
lib/ldp_sync.h \
|
||||
lib/lib_errors.h \
|
||||
lib/lib_vty.h \
|
||||
lib/libfrr.h \
|
||||
|
||||
@ -955,6 +955,14 @@ enum zapi_opaque_registry {
|
||||
LINK_STATE_REQUEST = 1,
|
||||
/* Update containing link-state db info */
|
||||
LINK_STATE_UPDATE = 2,
|
||||
/* Request LDP-SYNC state from LDP */
|
||||
LDP_IGP_SYNC_IF_STATE_REQUEST = 3,
|
||||
/* Update containing LDP IGP Sync State info */
|
||||
LDP_IGP_SYNC_IF_STATE_UPDATE = 4,
|
||||
/* Announce that LDP is up */
|
||||
LDP_IGP_SYNC_ANNOUNCE_UPDATE = 5,
|
||||
/* Heartbeat indicating that LDP is running */
|
||||
LDP_IGP_SYNC_HELLO_UPDATE = 6,
|
||||
};
|
||||
|
||||
/* Send the hello message.
|
||||
|
||||
@ -54,6 +54,7 @@ unsigned long conf_debug_ospf_te = 0;
|
||||
unsigned long conf_debug_ospf_ext = 0;
|
||||
unsigned long conf_debug_ospf_sr = 0;
|
||||
unsigned long conf_debug_ospf_defaultinfo = 0;
|
||||
unsigned long conf_debug_ospf_ldp_sync = 0;
|
||||
|
||||
/* Enable debug option variables -- valid only session. */
|
||||
unsigned long term_debug_ospf_packet[5] = {0, 0, 0, 0, 0};
|
||||
@ -67,6 +68,7 @@ unsigned long term_debug_ospf_te = 0;
|
||||
unsigned long term_debug_ospf_ext = 0;
|
||||
unsigned long term_debug_ospf_sr = 0;
|
||||
unsigned long term_debug_ospf_defaultinfo;
|
||||
unsigned long term_debug_ospf_ldp_sync;
|
||||
|
||||
const char *ospf_redist_string(unsigned int route_type)
|
||||
{
|
||||
@ -1476,6 +1478,32 @@ DEFUN (no_debug_ospf_default_info,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(debug_ospf_ldp_sync,
|
||||
debug_ospf_ldp_sync_cmd,
|
||||
"debug ospf ldp-sync",
|
||||
DEBUG_STR OSPF_STR
|
||||
"OSPF LDP-Sync information\n")
|
||||
{
|
||||
if (vty->node == CONFIG_NODE)
|
||||
CONF_DEBUG_ON(ldp_sync, LDP_SYNC);
|
||||
TERM_DEBUG_ON(ldp_sync, LDP_SYNC);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(no_debug_ospf_ldp_sync,
|
||||
no_debug_ospf_ldp_sync_cmd,
|
||||
"no debug ospf ldp-sync",
|
||||
NO_STR
|
||||
DEBUG_STR
|
||||
OSPF_STR
|
||||
"OSPF LDP-Sync information\n")
|
||||
{
|
||||
if (vty->node == CONFIG_NODE)
|
||||
CONF_DEBUG_OFF(ldp_sync, LDP_SYNC);
|
||||
TERM_DEBUG_OFF(ldp_sync, LDP_SYNC);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_debug_ospf,
|
||||
no_debug_ospf_cmd,
|
||||
"no debug ospf",
|
||||
@ -1505,6 +1533,7 @@ DEFUN (no_debug_ospf,
|
||||
DEBUG_OFF(zebra, ZEBRA_INTERFACE);
|
||||
DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE);
|
||||
DEBUG_OFF(defaultinfo, DEFAULTINFO);
|
||||
DEBUG_OFF(ldp_sync, LDP_SYNC);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
DEBUG_PACKET_OFF(i, flag);
|
||||
@ -1532,6 +1561,7 @@ DEFUN (no_debug_ospf,
|
||||
TERM_DEBUG_OFF(zebra, ZEBRA_INTERFACE);
|
||||
TERM_DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE);
|
||||
TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO);
|
||||
TERM_DEBUG_OFF(ldp_sync, LDP_SYNC);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -1633,6 +1663,10 @@ static int show_debugging_ospf_common(struct vty *vty, struct ospf *ospf)
|
||||
if (IS_DEBUG_OSPF(nssa, NSSA) == OSPF_DEBUG_NSSA)
|
||||
vty_out(vty, " OSPF NSSA debugging is on\n");
|
||||
|
||||
/* Show debug status for LDP-SYNC. */
|
||||
if (IS_DEBUG_OSPF(ldp_sync, LDP_SYNC) == OSPF_DEBUG_LDP_SYNC)
|
||||
vty_out(vty, " OSPF ldp-sync debugging is on\n");
|
||||
|
||||
vty_out(vty, "\n");
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -1814,6 +1848,11 @@ static int config_write_debug(struct vty *vty)
|
||||
write = 1;
|
||||
}
|
||||
|
||||
/* debug ospf ldp-sync */
|
||||
if (IS_CONF_DEBUG_OSPF(ldp_sync, LDP_SYNC) == OSPF_DEBUG_LDP_SYNC) {
|
||||
vty_out(vty, "debug ospf%s ldp-sync\n", str);
|
||||
write = 1;
|
||||
}
|
||||
return write;
|
||||
}
|
||||
|
||||
@ -1832,6 +1871,7 @@ void ospf_debug_init(void)
|
||||
install_element(ENABLE_NODE, &debug_ospf_te_cmd);
|
||||
install_element(ENABLE_NODE, &debug_ospf_sr_cmd);
|
||||
install_element(ENABLE_NODE, &debug_ospf_default_info_cmd);
|
||||
install_element(ENABLE_NODE, &debug_ospf_ldp_sync_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_ism_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_nsm_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_lsa_cmd);
|
||||
@ -1841,6 +1881,7 @@ void ospf_debug_init(void)
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_te_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_sr_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_default_info_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_ldp_sync_cmd);
|
||||
|
||||
install_element(ENABLE_NODE, &show_debugging_ospf_instance_cmd);
|
||||
install_element(ENABLE_NODE, &debug_ospf_packet_cmd);
|
||||
@ -1871,6 +1912,7 @@ void ospf_debug_init(void)
|
||||
install_element(CONFIG_NODE, &debug_ospf_te_cmd);
|
||||
install_element(CONFIG_NODE, &debug_ospf_sr_cmd);
|
||||
install_element(CONFIG_NODE, &debug_ospf_default_info_cmd);
|
||||
install_element(CONFIG_NODE, &debug_ospf_ldp_sync_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_nsm_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_lsa_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_zebra_cmd);
|
||||
@ -1879,6 +1921,7 @@ void ospf_debug_init(void)
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_te_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_sr_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_default_info_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_ldp_sync_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &debug_ospf_instance_nsm_cmd);
|
||||
install_element(CONFIG_NODE, &debug_ospf_instance_lsa_cmd);
|
||||
|
||||
@ -60,6 +60,7 @@
|
||||
#define OSPF_DEBUG_EXT 0x08
|
||||
#define OSPF_DEBUG_SR 0x10
|
||||
#define OSPF_DEBUG_DEFAULTINFO 0x20
|
||||
#define OSPF_DEBUG_LDP_SYNC 0x40
|
||||
|
||||
/* Macro for setting debug option. */
|
||||
#define CONF_DEBUG_PACKET_ON(a, b) conf_debug_ospf_packet[a] |= (b)
|
||||
@ -107,6 +108,8 @@
|
||||
|
||||
#define IS_DEBUG_OSPF_DEFAULT_INFO IS_DEBUG_OSPF(defaultinfo, DEFAULTINFO)
|
||||
|
||||
#define IS_DEBUG_OSPF_LDP_SYNC IS_DEBUG_OSPF(ldp_sync, LDP_SYNC)
|
||||
|
||||
#define IS_CONF_DEBUG_OSPF_PACKET(a, b) \
|
||||
(conf_debug_ospf_packet[a] & OSPF_DEBUG_##b)
|
||||
#define IS_CONF_DEBUG_OSPF(a, b) (conf_debug_ospf_##a & OSPF_DEBUG_##b)
|
||||
@ -126,6 +129,7 @@ extern unsigned long term_debug_ospf_te;
|
||||
extern unsigned long term_debug_ospf_ext;
|
||||
extern unsigned long term_debug_ospf_sr;
|
||||
extern unsigned long term_debug_ospf_defaultinfo;
|
||||
extern unsigned long term_debug_ospf_ldp_sync;
|
||||
|
||||
/* Message Strings. */
|
||||
extern char *ospf_lsa_type_str[];
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#include "log.h"
|
||||
#include "zclient.h"
|
||||
#include "bfd.h"
|
||||
#include "ldp_sync.h"
|
||||
|
||||
#include "ospfd/ospfd.h"
|
||||
#include "ospfd/ospf_spf.h"
|
||||
@ -46,6 +47,7 @@
|
||||
#include "ospfd/ospf_abr.h"
|
||||
#include "ospfd/ospf_network.h"
|
||||
#include "ospfd/ospf_dump.h"
|
||||
#include "ospfd/ospf_ldp_sync.h"
|
||||
|
||||
DEFINE_QOBJ_TYPE(ospf_interface)
|
||||
DEFINE_HOOK(ospf_vl_add, (struct ospf_vl_data * vd), (vd))
|
||||
@ -81,6 +83,12 @@ int ospf_if_get_output_cost(struct ospf_interface *oi)
|
||||
uint32_t cost;
|
||||
uint32_t bw, refbw;
|
||||
|
||||
/* if LDP-IGP Sync is running on interface set cost so interface
|
||||
* is used only as last resort
|
||||
*/
|
||||
if (ldp_sync_if_is_enabled(IF_DEF_PARAMS(oi->ifp)->ldp_sync_info))
|
||||
return (LDP_OSPF_LSINFINITY);
|
||||
|
||||
/* ifp speed and bw can be 0 in some platforms, use ospf default bw
|
||||
if bw is configured under interface it would be used.
|
||||
*/
|
||||
@ -539,6 +547,7 @@ void ospf_del_if_params(struct ospf_if_params *oip)
|
||||
{
|
||||
list_delete(&oip->auth_crypt);
|
||||
bfd_info_free(&(oip->bfd_info));
|
||||
ldp_sync_info_free(&(oip->ldp_sync_info));
|
||||
XFREE(MTYPE_OSPF_IF_PARAMS, oip);
|
||||
}
|
||||
|
||||
|
||||
@ -104,6 +104,9 @@ struct ospf_if_params {
|
||||
|
||||
/* BFD configuration */
|
||||
struct bfd_info *bfd_info;
|
||||
|
||||
/* MPLS LDP-IGP Sync configuration */
|
||||
struct ldp_sync_info *ldp_sync_info;
|
||||
};
|
||||
|
||||
enum { MEMBER_ALLROUTERS = 0,
|
||||
|
||||
1142
ospfd/ospf_ldp_sync.c
Normal file
1142
ospfd/ospf_ldp_sync.c
Normal file
File diff suppressed because it is too large
Load Diff
56
ospfd/ospf_ldp_sync.h
Normal file
56
ospfd/ospf_ldp_sync.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* ospf_ldp_sync.h: OSPF LDP-IGP Sync handling routines
|
||||
* 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 General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_OSPF_LDP_SYNC_H
|
||||
#define _ZEBRA_OSPF_LDP_SYNC_H
|
||||
|
||||
#define LDP_OSPF_LSINFINITY 65535
|
||||
|
||||
/* Macro to log debug message */
|
||||
#define ols_debug(...) \
|
||||
do { \
|
||||
if (IS_DEBUG_OSPF_LDP_SYNC) \
|
||||
zlog_debug(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
|
||||
extern void ospf_if_set_ldp_sync_enable(struct ospf *ospf,
|
||||
struct interface *ifp);
|
||||
extern void ospf_if_set_ldp_sync_holddown(struct ospf *ospf,
|
||||
struct interface *ifp);
|
||||
extern void ospf_ldp_sync_if_init(struct ospf_interface *ospf);
|
||||
extern void ospf_ldp_sync_if_start(struct interface *ifp, bool send_state_req);
|
||||
extern void ospf_ldp_sync_if_remove(struct interface *ifp, bool remove);
|
||||
extern void ospf_ldp_sync_if_down(struct interface *ifp);
|
||||
extern void ospf_ldp_sync_if_complete(struct interface *ifp);
|
||||
extern void ospf_ldp_sync_holddown_timer_add(struct interface *ifp);
|
||||
extern void ospf_ldp_sync_hello_timer_add(struct ospf *ospf);
|
||||
extern void ospf_ldp_sync_ldp_fail(struct interface *ifp);
|
||||
extern void ospf_ldp_sync_show_info(struct vty *vty, struct ospf *ospf,
|
||||
json_object *json_vrf, bool use_json);
|
||||
extern void ospf_ldp_sync_write_config(struct vty *vty, struct ospf *ospf);
|
||||
extern void ospf_ldp_sync_if_write_config(struct vty *vty,
|
||||
struct ospf_if_params *params);
|
||||
extern int ospf_ldp_sync_state_update(struct ldp_igp_sync_if_state state);
|
||||
extern int ospf_ldp_sync_announce_update(struct ldp_igp_sync_announce announce);
|
||||
extern int ospf_ldp_sync_hello_update(struct ldp_igp_sync_hello hello);
|
||||
extern void ospf_ldp_sync_state_req_msg(struct interface *ifp);
|
||||
extern void ospf_ldp_sync_init(void);
|
||||
extern void ospf_ldp_sync_gbl_exit(struct ospf *ospf, bool remove);
|
||||
#endif /* _ZEBRA_OSPF_LDP_SYNC_H */
|
||||
@ -54,6 +54,7 @@
|
||||
#include "ospfd/ospf_vty.h"
|
||||
#include "ospfd/ospf_bfd.h"
|
||||
#include "ospfd/ospf_errors.h"
|
||||
#include "ospfd/ospf_ldp_sync.h"
|
||||
|
||||
/* ospfd privileges */
|
||||
zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN,
|
||||
@ -217,6 +218,9 @@ int main(int argc, char **argv)
|
||||
/* OSPF BFD init */
|
||||
ospf_bfd_init();
|
||||
|
||||
/* OSPF LDP IGP Sync init */
|
||||
ospf_ldp_sync_init();
|
||||
|
||||
ospf_route_map_init();
|
||||
ospf_opaque_init();
|
||||
|
||||
|
||||
@ -52,6 +52,7 @@
|
||||
#include "ospfd/ospf_vty.h"
|
||||
#include "ospfd/ospf_dump.h"
|
||||
#include "ospfd/ospf_bfd.h"
|
||||
#include "ospfd/ospf_ldp_sync.h"
|
||||
|
||||
FRR_CFG_DEFAULT_BOOL(OSPF_LOG_ADJACENCY_CHANGES,
|
||||
{ .val_bool = true, .match_profile = "datacenter", },
|
||||
@ -3222,6 +3223,10 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf,
|
||||
vty_out(vty, " Adjacency changes are logged\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* show LDP-Sync status */
|
||||
ospf_ldp_sync_show_info(vty, ospf, json_vrf, json ? 1 : 0);
|
||||
|
||||
/* Show each area status. */
|
||||
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
|
||||
show_ip_ospf_area(vty, area, json_areas, json ? 1 : 0);
|
||||
@ -9975,6 +9980,9 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
/* LDP-Sync print */
|
||||
if (params && params->ldp_sync_info)
|
||||
ospf_ldp_sync_if_write_config(vty, params);
|
||||
|
||||
while (1) {
|
||||
if (rn == NULL)
|
||||
@ -10498,6 +10506,9 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf)
|
||||
|
||||
ospf_opaque_config_write_router(vty, ospf);
|
||||
|
||||
/* LDP-Sync print */
|
||||
ospf_ldp_sync_write_config(vty, ospf);
|
||||
|
||||
write++;
|
||||
return write;
|
||||
}
|
||||
|
||||
@ -51,6 +51,7 @@
|
||||
#include "ospfd/ospf_zebra.h"
|
||||
#include "ospfd/ospf_te.h"
|
||||
#include "ospfd/ospf_sr.h"
|
||||
#include "ospfd/ospf_ldp_sync.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table")
|
||||
DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute")
|
||||
@ -1833,6 +1834,45 @@ static void ospf_zebra_connected(struct zclient *zclient)
|
||||
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
||||
}
|
||||
|
||||
/*
|
||||
* opaque messages between processes
|
||||
*/
|
||||
static int ospf_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_opaque_msg info;
|
||||
struct ldp_igp_sync_if_state state;
|
||||
struct ldp_igp_sync_announce announce;
|
||||
struct ldp_igp_sync_hello hello;
|
||||
int ret = 0;
|
||||
|
||||
s = zclient->ibuf;
|
||||
|
||||
if (zclient_opaque_decode(s, &info) != 0)
|
||||
return -1;
|
||||
|
||||
switch (info.type) {
|
||||
case LDP_IGP_SYNC_IF_STATE_UPDATE:
|
||||
STREAM_GET(&state, s, sizeof(state));
|
||||
ret = ospf_ldp_sync_state_update(state);
|
||||
break;
|
||||
case LDP_IGP_SYNC_ANNOUNCE_UPDATE:
|
||||
STREAM_GET(&announce, s, sizeof(announce));
|
||||
ret = ospf_ldp_sync_announce_update(announce);
|
||||
break;
|
||||
case LDP_IGP_SYNC_HELLO_UPDATE:
|
||||
STREAM_GET(&hello, s, sizeof(hello));
|
||||
ret = ospf_ldp_sync_hello_update(hello);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
stream_failure:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ospf_zebra_init(struct thread_master *master, unsigned short instance)
|
||||
{
|
||||
/* Allocate zebra structure. */
|
||||
@ -1866,6 +1906,8 @@ void ospf_zebra_init(struct thread_master *master, unsigned short instance)
|
||||
access_list_delete_hook(ospf_filter_update);
|
||||
prefix_list_add_hook(ospf_prefix_list_update);
|
||||
prefix_list_delete_hook(ospf_prefix_list_update);
|
||||
|
||||
zclient->opaque_msg_handler = ospf_opaque_msg_handler;
|
||||
}
|
||||
|
||||
void ospf_zebra_send_arp(const struct interface *ifp, const struct prefix *p)
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
#include "libfrr.h"
|
||||
#include "defaults.h"
|
||||
#include "lib_errors.h"
|
||||
#include "ldp_sync.h"
|
||||
|
||||
#include "ospfd/ospfd.h"
|
||||
#include "ospfd/ospf_network.h"
|
||||
@ -57,6 +58,7 @@
|
||||
#include "ospfd/ospf_abr.h"
|
||||
#include "ospfd/ospf_flood.h"
|
||||
#include "ospfd/ospf_ase.h"
|
||||
#include "ospfd/ospf_ldp_sync.h"
|
||||
|
||||
|
||||
DEFINE_QOBJ_TYPE(ospf)
|
||||
@ -619,6 +621,10 @@ static void ospf_finish_final(struct ospf *ospf)
|
||||
|
||||
list_delete(&ospf->vlinks);
|
||||
|
||||
/* shutdown LDP-Sync */
|
||||
if (ospf->vrf_id == VRF_DEFAULT)
|
||||
ospf_ldp_sync_gbl_exit(ospf, true);
|
||||
|
||||
/* Remove any ospf interface config params */
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
struct ospf_if_params *params;
|
||||
@ -948,6 +954,9 @@ static void add_ospf_interface(struct connected *co, struct ospf_area *area)
|
||||
|
||||
ospf_area_add_if(oi->area, oi);
|
||||
|
||||
/* if LDP-IGP Sync is configured globally inherit config */
|
||||
ospf_ldp_sync_if_init(oi);
|
||||
|
||||
/*
|
||||
* if router_id is not configured, dont bring up
|
||||
* interfaces.
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include <zebra.h>
|
||||
#include "qobj.h"
|
||||
#include "libospf.h"
|
||||
#include "ldp_sync.h"
|
||||
|
||||
#include "filter.h"
|
||||
#include "log.h"
|
||||
@ -320,6 +321,9 @@ struct ospf {
|
||||
struct list *external[ZEBRA_ROUTE_MAX + 1];
|
||||
#define EXTERNAL_INFO(E) (E->external_info)
|
||||
|
||||
/* MPLS LDP-IGP Sync */
|
||||
struct ldp_sync_info_cmd ldp_sync_cmd;
|
||||
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
DECLARE_QOBJ_TYPE(ospf)
|
||||
|
||||
@ -9,6 +9,7 @@ dist_examples_DATA += ospfd/ospfd.conf.sample
|
||||
vtysh_scan += \
|
||||
ospfd/ospf_bfd.c \
|
||||
ospfd/ospf_dump.c \
|
||||
ospfd/ospf_ldp_sync.c \
|
||||
ospfd/ospf_opaque.c \
|
||||
ospfd/ospf_ri.c \
|
||||
ospfd/ospf_routemap.c \
|
||||
@ -37,6 +38,7 @@ ospfd_libfrrospf_a_SOURCES = \
|
||||
ospfd/ospf_ia.c \
|
||||
ospfd/ospf_interface.c \
|
||||
ospfd/ospf_ism.c \
|
||||
ospfd/ospf_ldp_sync.c \
|
||||
ospfd/ospf_lsa.c \
|
||||
ospfd/ospf_lsdb.c \
|
||||
ospfd/ospf_memory.c \
|
||||
@ -74,6 +76,7 @@ endif
|
||||
|
||||
clippy_scan += \
|
||||
ospfd/ospf_vty.c \
|
||||
ospfd/ospf_ldp_sync.c \
|
||||
# end
|
||||
|
||||
noinst_HEADERS += \
|
||||
@ -86,6 +89,7 @@ noinst_HEADERS += \
|
||||
ospfd/ospf_flood.h \
|
||||
ospfd/ospf_ia.h \
|
||||
ospfd/ospf_interface.h \
|
||||
ospfd/ospf_ldp_sync.h \
|
||||
ospfd/ospf_memory.h \
|
||||
ospfd/ospf_neighbor.h \
|
||||
ospfd/ospf_network.h \
|
||||
|
||||
12
tests/topotests/ldp-sync-isis-topo1/ce1/zebra.conf
Normal file
12
tests/topotests/ldp-sync-isis-topo1/ce1/zebra.conf
Normal file
@ -0,0 +1,12 @@
|
||||
log file zebra.log
|
||||
!
|
||||
hostname ce1
|
||||
!
|
||||
interface ce1-eth0
|
||||
ip address 172.16.1.1/24
|
||||
no link-detect
|
||||
!
|
||||
ip forwarding
|
||||
!
|
||||
line vty
|
||||
!
|
||||
12
tests/topotests/ldp-sync-isis-topo1/ce2/zebra.conf
Normal file
12
tests/topotests/ldp-sync-isis-topo1/ce2/zebra.conf
Normal file
@ -0,0 +1,12 @@
|
||||
log file zebra.log
|
||||
!
|
||||
hostname ce2
|
||||
!
|
||||
interface ce2-eth0
|
||||
ip address 172.16.1.2/24
|
||||
no link-detect
|
||||
!
|
||||
ip forwarding
|
||||
!
|
||||
line vty
|
||||
!
|
||||
12
tests/topotests/ldp-sync-isis-topo1/ce3/zebra.conf
Normal file
12
tests/topotests/ldp-sync-isis-topo1/ce3/zebra.conf
Normal file
@ -0,0 +1,12 @@
|
||||
log file zebra.log
|
||||
!
|
||||
hostname ce3
|
||||
!
|
||||
interface ce3-eth0
|
||||
ip address 172.16.1.3/24
|
||||
no link-detect
|
||||
!
|
||||
ip forwarding
|
||||
!
|
||||
line vty
|
||||
!
|
||||
26
tests/topotests/ldp-sync-isis-topo1/r1/isisd.conf
Normal file
26
tests/topotests/ldp-sync-isis-topo1/r1/isisd.conf
Normal file
@ -0,0 +1,26 @@
|
||||
hostname r1
|
||||
log file isisd.log
|
||||
debug isis adj-packets
|
||||
debug isis events
|
||||
debug isis update-packets
|
||||
debug isis ldp-sync
|
||||
!
|
||||
router isis 1
|
||||
net 10.0000.0000.0000.0000.0000.0000.0000.0000.0001.00
|
||||
metric-style wide
|
||||
redistribute ipv4 connected level-1
|
||||
redistribute ipv6 connected level-1
|
||||
mpls ldp-sync
|
||||
!
|
||||
interface r1-eth1
|
||||
ip router isis 1
|
||||
ipv6 router isis 1
|
||||
isis network point-to-point
|
||||
isis circuit-type level-1
|
||||
!
|
||||
interface r1-eth2
|
||||
ip router isis 1
|
||||
ipv6 router isis 1
|
||||
isis network point-to-point
|
||||
isis circuit-type level-1
|
||||
!
|
||||
33
tests/topotests/ldp-sync-isis-topo1/r1/ldpd.conf
Normal file
33
tests/topotests/ldp-sync-isis-topo1/r1/ldpd.conf
Normal file
@ -0,0 +1,33 @@
|
||||
hostname r1
|
||||
log file ldpd.log
|
||||
!
|
||||
debug mpls ldp zebra
|
||||
debug mpls ldp event
|
||||
debug mpls ldp errors
|
||||
debug mpls ldp sync
|
||||
!
|
||||
mpls ldp
|
||||
router-id 1.1.1.1
|
||||
!
|
||||
address-family ipv4
|
||||
discovery transport-address 1.1.1.1
|
||||
label local allocate host-routes
|
||||
!
|
||||
ttl-security disable
|
||||
!
|
||||
interface r1-eth1
|
||||
!
|
||||
interface r1-eth2
|
||||
!
|
||||
!
|
||||
!
|
||||
l2vpn CUST_A type vpls
|
||||
member interface r1-eth0
|
||||
!
|
||||
member pseudowire r1-mpw0
|
||||
neighbor lsr-id 2.2.2.2
|
||||
pw-id 100
|
||||
!
|
||||
!
|
||||
line vty
|
||||
!
|
||||
143
tests/topotests/ldp-sync-isis-topo1/r1/show_ip_route.ref
Normal file
143
tests/topotests/ldp-sync-isis-topo1/r1/show_ip_route.ref
Normal file
@ -0,0 +1,143 @@
|
||||
{
|
||||
"1.1.1.1\/32":[
|
||||
{
|
||||
"prefix":"1.1.1.1\/32",
|
||||
"protocol":"connected",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"directlyConnected":true,
|
||||
"interfaceIndex":1,
|
||||
"interfaceName":"lo",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2.2.2.2\/32":[
|
||||
{
|
||||
"prefix":"2.2.2.2\/32",
|
||||
"protocol":"isis",
|
||||
"selected":true,
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.1.2",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r1-eth1",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"3.3.3.3\/32":[
|
||||
{
|
||||
"prefix":"3.3.3.3\/32",
|
||||
"protocol":"isis",
|
||||
"selected":true,
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.2.3",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r1-eth2",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"10.0.1.0\/24":[
|
||||
{
|
||||
"prefix":"10.0.1.0\/24",
|
||||
"protocol":"isis",
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"10.0.1.2",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r1-eth1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"prefix":"10.0.1.0\/24",
|
||||
"protocol":"connected",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"directlyConnected":true,
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r1-eth1",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"10.0.2.0\/24":[
|
||||
{
|
||||
"prefix":"10.0.2.0\/24",
|
||||
"protocol":"isis",
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"10.0.2.3",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r1-eth2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"prefix":"10.0.2.0\/24",
|
||||
"protocol":"connected",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"directlyConnected":true,
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r1-eth2",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"10.0.3.0\/24":[
|
||||
{
|
||||
"prefix":"10.0.3.0\/24",
|
||||
"protocol":"isis",
|
||||
"selected":true,
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.1.2",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r1-eth1",
|
||||
"active":true
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.2.3",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r1-eth2",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"1": {
|
||||
"r1-eth1": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
],
|
||||
"r1-eth2": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"1": {
|
||||
"r1-eth1": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "16777214"
|
||||
}
|
||||
],
|
||||
"r1-eth2": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"1": {
|
||||
"r1-eth1": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "16777214"
|
||||
}
|
||||
],
|
||||
"r1-eth2": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
"r1-eth1":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync achieved"
|
||||
},
|
||||
"r1-eth2":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync achieved"
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
"r1-eth1":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync not achieved"
|
||||
},
|
||||
"r1-eth2":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync achieved"
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
"r1-eth1":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync not achieved"
|
||||
},
|
||||
"r1-eth2":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync achieved"
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"2.2.2.2: 100":{
|
||||
"destination":"2.2.2.2",
|
||||
"vcId":100,
|
||||
"localLabel":16,
|
||||
"localControlWord":1,
|
||||
"localVcType":"Ethernet",
|
||||
"localGroupID":0,
|
||||
"localIfMtu":1500,
|
||||
"remoteLabel":16,
|
||||
"remoteControlWord":1,
|
||||
"remoteVcType":"Ethernet",
|
||||
"remoteGroupID":0,
|
||||
"remoteIfMtu":1500
|
||||
}
|
||||
}
|
||||
8
tests/topotests/ldp-sync-isis-topo1/r1/show_l2vpn_vc.ref
Normal file
8
tests/topotests/ldp-sync-isis-topo1/r1/show_l2vpn_vc.ref
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"r1-mpw0":{
|
||||
"peerId":"2.2.2.2",
|
||||
"vcId":100,
|
||||
"VpnName":"CUST_A",
|
||||
"status":"up"
|
||||
}
|
||||
}
|
||||
44
tests/topotests/ldp-sync-isis-topo1/r1/show_ldp_binding.ref
Normal file
44
tests/topotests/ldp-sync-isis-topo1/r1/show_ldp_binding.ref
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"bindings":[
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"1.1.1.1/32",
|
||||
"neighborId":"2.2.2.2",
|
||||
"localLabel":"imp-null",
|
||||
"inUse":0
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"1.1.1.1/32",
|
||||
"neighborId":"3.3.3.3",
|
||||
"localLabel":"imp-null",
|
||||
"inUse":0
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"2.2.2.2/32",
|
||||
"neighborId":"2.2.2.2",
|
||||
"remoteLabel":"imp-null",
|
||||
"inUse":1
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"2.2.2.2/32",
|
||||
"neighborId":"3.3.3.3",
|
||||
"inUse":0
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"3.3.3.3/32",
|
||||
"neighborId":"2.2.2.2",
|
||||
"inUse":0
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"3.3.3.3/32",
|
||||
"neighborId":"3.3.3.3",
|
||||
"remoteLabel":"imp-null",
|
||||
"inUse":1
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
{
|
||||
"adjacencies":[
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"neighborId":"2.2.2.2",
|
||||
"type":"link",
|
||||
"interface":"r1-eth1",
|
||||
"helloHoldtime":15
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"neighborId":"2.2.2.2",
|
||||
"type":"targeted",
|
||||
"peer":"2.2.2.2",
|
||||
"helloHoldtime":45
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"neighborId":"3.3.3.3",
|
||||
"type":"link",
|
||||
"interface":"r1-eth2",
|
||||
"helloHoldtime":15
|
||||
}
|
||||
]
|
||||
}
|
||||
16
tests/topotests/ldp-sync-isis-topo1/r1/show_ldp_igp_sync.ref
Normal file
16
tests/topotests/ldp-sync-isis-topo1/r1/show_ldp_igp_sync.ref
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"r1-eth1":{
|
||||
"state":"labelExchangeComplete",
|
||||
"waitTime":10,
|
||||
"waitTimeRemaining":0,
|
||||
"timerRunning":false,
|
||||
"peerLdpId":"2.2.2.2"
|
||||
},
|
||||
"r1-eth2":{
|
||||
"state":"labelExchangeComplete",
|
||||
"waitTime":10,
|
||||
"waitTimeRemaining":0,
|
||||
"timerRunning":false,
|
||||
"peerLdpId":"3.3.3.3"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"r1-eth1":{
|
||||
"state":"labelExchangeNotComplete",
|
||||
"waitTime":10,
|
||||
"waitTimeRemaining":0,
|
||||
"timerRunning":false,
|
||||
"peerLdpId":""
|
||||
},
|
||||
"r1-eth2":{
|
||||
"state":"labelExchangeComplete",
|
||||
"waitTime":10,
|
||||
"waitTimeRemaining":0,
|
||||
"timerRunning":false,
|
||||
"peerLdpId":"3.3.3.3"
|
||||
}
|
||||
}
|
||||
16
tests/topotests/ldp-sync-isis-topo1/r1/show_ldp_neighbor.ref
Normal file
16
tests/topotests/ldp-sync-isis-topo1/r1/show_ldp_neighbor.ref
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"neighbors":[
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"neighborId":"2.2.2.2",
|
||||
"state":"OPERATIONAL",
|
||||
"transportAddress":"2.2.2.2"
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"neighborId":"3.3.3.3",
|
||||
"state":"OPERATIONAL",
|
||||
"transportAddress":"3.3.3.3"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
{
|
||||
"frr-interface:lib": {
|
||||
"interface": [
|
||||
{
|
||||
"name": "r1-eth1",
|
||||
"vrf": "default",
|
||||
"state": {
|
||||
"frr-isisd:isis": {
|
||||
"adjacencies": {
|
||||
"adjacency": [
|
||||
{
|
||||
"neighbor-sys-type": "level-1",
|
||||
"neighbor-sysid": "0000.0000.0002",
|
||||
"neighbor-extended-circuit-id": 0,
|
||||
"state": "up"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "r1-eth2",
|
||||
"vrf": "default",
|
||||
"state": {
|
||||
"frr-isisd:isis": {
|
||||
"adjacencies": {
|
||||
"adjacency": [
|
||||
{
|
||||
"neighbor-sys-type": "level-1",
|
||||
"neighbor-sysid": "0000.0000.0003",
|
||||
"neighbor-extended-circuit-id": 0,
|
||||
"state": "up"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
29
tests/topotests/ldp-sync-isis-topo1/r1/zebra.conf
Normal file
29
tests/topotests/ldp-sync-isis-topo1/r1/zebra.conf
Normal file
@ -0,0 +1,29 @@
|
||||
log file zebra.log
|
||||
!
|
||||
hostname r1
|
||||
!
|
||||
debug zebra kernel
|
||||
debug zebra rib detailed
|
||||
debug zebra dplane detailed
|
||||
debug zebra nht
|
||||
debug zebra pseudowires
|
||||
debug zebra mpls
|
||||
!
|
||||
interface lo
|
||||
ip address 1.1.1.1/32
|
||||
!
|
||||
interface r1-eth0
|
||||
description to s1
|
||||
!
|
||||
interface r1-eth1
|
||||
description to s4
|
||||
ip address 10.0.1.1/24
|
||||
!
|
||||
interface r1-eth2
|
||||
description to s5
|
||||
ip address 10.0.2.1/24
|
||||
!
|
||||
ip forwarding
|
||||
!
|
||||
line vty
|
||||
!
|
||||
27
tests/topotests/ldp-sync-isis-topo1/r2/isisd.conf
Normal file
27
tests/topotests/ldp-sync-isis-topo1/r2/isisd.conf
Normal file
@ -0,0 +1,27 @@
|
||||
hostname r2
|
||||
log file isisd.log
|
||||
debug isis adj-packets
|
||||
debug isis events
|
||||
debug isis update-packets
|
||||
debug isis ldp-sync
|
||||
!
|
||||
router isis 1
|
||||
net 10.0000.0000.0000.0000.0000.0000.0000.0000.0002.00
|
||||
metric-style wide
|
||||
redistribute ipv4 connected level-1
|
||||
redistribute ipv6 connected level-1
|
||||
mpls ldp-sync
|
||||
!
|
||||
interface r2-eth1
|
||||
ip router isis 1
|
||||
ipv6 router isis 1
|
||||
isis network point-to-point
|
||||
isis circuit-type level-1
|
||||
!
|
||||
interface r2-eth2
|
||||
ip router isis 1
|
||||
ipv6 router isis 1
|
||||
isis network point-to-point
|
||||
isis circuit-type level-1
|
||||
no isis mpls ldp-sync
|
||||
!
|
||||
33
tests/topotests/ldp-sync-isis-topo1/r2/ldpd.conf
Normal file
33
tests/topotests/ldp-sync-isis-topo1/r2/ldpd.conf
Normal file
@ -0,0 +1,33 @@
|
||||
hostname r2
|
||||
log file ldpd.log
|
||||
!
|
||||
debug mpls ldp zebra
|
||||
debug mpls ldp event
|
||||
debug mpls ldp errors
|
||||
debug mpls ldp sync
|
||||
!
|
||||
mpls ldp
|
||||
router-id 2.2.2.2
|
||||
!
|
||||
address-family ipv4
|
||||
discovery transport-address 2.2.2.2
|
||||
label local allocate host-routes
|
||||
!
|
||||
ttl-security disable
|
||||
!
|
||||
interface r2-eth1
|
||||
!
|
||||
interface r2-eth2
|
||||
!
|
||||
!
|
||||
!
|
||||
l2vpn CUST_A type vpls
|
||||
member interface r2-eth0
|
||||
!
|
||||
member pseudowire r2-mpw0
|
||||
neighbor lsr-id 1.1.1.1
|
||||
pw-id 100
|
||||
!
|
||||
!
|
||||
line vty
|
||||
!
|
||||
19
tests/topotests/ldp-sync-isis-topo1/r2/ospfd.conf
Normal file
19
tests/topotests/ldp-sync-isis-topo1/r2/ospfd.conf
Normal file
@ -0,0 +1,19 @@
|
||||
hostname r2
|
||||
log file ospfd.log
|
||||
debug ospf zebra interface
|
||||
debug ospf ldp-sync
|
||||
!
|
||||
router ospf
|
||||
router-id 2.2.2.2
|
||||
network 0.0.0.0/0 area 0
|
||||
mpls ldp-sync
|
||||
mpls ldp-sync holddown 50
|
||||
!
|
||||
interface r2-eth1
|
||||
ip ospf network point-to-point
|
||||
ip ospf mpls ldp-sync holddown 300
|
||||
!
|
||||
interface r2-eth2
|
||||
ip ospf network point-to-point
|
||||
no ip ospf mpls ldp-sync
|
||||
!
|
||||
143
tests/topotests/ldp-sync-isis-topo1/r2/show_ip_route.ref
Normal file
143
tests/topotests/ldp-sync-isis-topo1/r2/show_ip_route.ref
Normal file
@ -0,0 +1,143 @@
|
||||
{
|
||||
"1.1.1.1\/32":[
|
||||
{
|
||||
"prefix":"1.1.1.1\/32",
|
||||
"protocol":"isis",
|
||||
"selected":true,
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.1.1",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r2-eth1",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2.2.2.2\/32":[
|
||||
{
|
||||
"prefix":"2.2.2.2\/32",
|
||||
"protocol":"connected",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"directlyConnected":true,
|
||||
"interfaceIndex":1,
|
||||
"interfaceName":"lo",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"3.3.3.3\/32":[
|
||||
{
|
||||
"prefix":"3.3.3.3\/32",
|
||||
"protocol":"isis",
|
||||
"selected":true,
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.3.3",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r2-eth2",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"10.0.1.0\/24":[
|
||||
{
|
||||
"prefix":"10.0.1.0\/24",
|
||||
"protocol":"isis",
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"10.0.1.1",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r2-eth1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"prefix":"10.0.1.0\/24",
|
||||
"protocol":"connected",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"directlyConnected":true,
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r2-eth1",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"10.0.2.0\/24":[
|
||||
{
|
||||
"prefix":"10.0.2.0\/24",
|
||||
"protocol":"isis",
|
||||
"selected":true,
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.1.1",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r2-eth1",
|
||||
"active":true
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.3.3",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r2-eth2",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"10.0.3.0\/24":[
|
||||
{
|
||||
"prefix":"10.0.3.0\/24",
|
||||
"protocol":"isis",
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"10.0.3.3",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r2-eth2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"prefix":"10.0.3.0\/24",
|
||||
"protocol":"connected",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"directlyConnected":true,
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r2-eth2",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"1": {
|
||||
"r2-eth1": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
],
|
||||
"r2-eth2": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"1": {
|
||||
"r2-eth1": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "16777214"
|
||||
}
|
||||
],
|
||||
"r2-eth2": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"1": {
|
||||
"r2-eth1": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "16777214"
|
||||
}
|
||||
],
|
||||
"r2-eth2": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
"r2-eth1":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync achieved"
|
||||
},
|
||||
"r2-eth2":{
|
||||
"ldpIgpSyncEnabled":false,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync not required"
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
"r2-eth1":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync not achieved"
|
||||
},
|
||||
"r2-eth2":{
|
||||
"ldpIgpSyncEnabled":false,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync not required"
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
"r2-eth1":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync not achieved"
|
||||
},
|
||||
"r2-eth2":{
|
||||
"ldpIgpSyncEnabled":false,
|
||||
"holdDownTimeInSec":0,
|
||||
"ldpIgpSyncState":"Sync not required"
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"1.1.1.1: 100":{
|
||||
"destination":"1.1.1.1",
|
||||
"vcId":100,
|
||||
"localLabel":16,
|
||||
"localControlWord":1,
|
||||
"localVcType":"Ethernet",
|
||||
"localGroupID":0,
|
||||
"localIfMtu":1500,
|
||||
"remoteLabel":16,
|
||||
"remoteControlWord":1,
|
||||
"remoteVcType":"Ethernet",
|
||||
"remoteGroupID":0,
|
||||
"remoteIfMtu":1500
|
||||
}
|
||||
}
|
||||
8
tests/topotests/ldp-sync-isis-topo1/r2/show_l2vpn_vc.ref
Normal file
8
tests/topotests/ldp-sync-isis-topo1/r2/show_l2vpn_vc.ref
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"r2-mpw0":{
|
||||
"peerId":"1.1.1.1",
|
||||
"vcId":100,
|
||||
"VpnName":"CUST_A",
|
||||
"status":"up"
|
||||
}
|
||||
}
|
||||
44
tests/topotests/ldp-sync-isis-topo1/r2/show_ldp_binding.ref
Normal file
44
tests/topotests/ldp-sync-isis-topo1/r2/show_ldp_binding.ref
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"bindings":[
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"1.1.1.1/32",
|
||||
"neighborId":"1.1.1.1",
|
||||
"remoteLabel":"imp-null",
|
||||
"inUse":1
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"1.1.1.1/32",
|
||||
"neighborId":"3.3.3.3",
|
||||
"inUse":0
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"2.2.2.2/32",
|
||||
"neighborId":"1.1.1.1",
|
||||
"localLabel":"imp-null",
|
||||
"inUse":0
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"2.2.2.2/32",
|
||||
"neighborId":"3.3.3.3",
|
||||
"localLabel":"imp-null",
|
||||
"inUse":0
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"3.3.3.3/32",
|
||||
"neighborId":"1.1.1.1",
|
||||
"inUse":0
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"prefix":"3.3.3.3/32",
|
||||
"neighborId":"3.3.3.3",
|
||||
"remoteLabel":"imp-null",
|
||||
"inUse":1
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
{
|
||||
"adjacencies":[
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"neighborId":"1.1.1.1",
|
||||
"type":"link",
|
||||
"interface":"r2-eth1",
|
||||
"helloHoldtime":15
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"neighborId":"1.1.1.1",
|
||||
"type":"targeted",
|
||||
"peer":"1.1.1.1",
|
||||
"helloHoldtime":45
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"neighborId":"3.3.3.3",
|
||||
"type":"link",
|
||||
"interface":"r2-eth2",
|
||||
"helloHoldtime":15
|
||||
}
|
||||
]
|
||||
}
|
||||
16
tests/topotests/ldp-sync-isis-topo1/r2/show_ldp_igp_sync.ref
Normal file
16
tests/topotests/ldp-sync-isis-topo1/r2/show_ldp_igp_sync.ref
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"r2-eth1":{
|
||||
"state":"labelExchangeComplete",
|
||||
"waitTime":10,
|
||||
"waitTimeRemaining":0,
|
||||
"timerRunning":false,
|
||||
"peerLdpId":"1.1.1.1"
|
||||
},
|
||||
"r2-eth2":{
|
||||
"state":"labelExchangeComplete",
|
||||
"waitTime":10,
|
||||
"waitTimeRemaining":0,
|
||||
"timerRunning":false,
|
||||
"peerLdpId":"3.3.3.3"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"r2-eth1":{
|
||||
"state":"labelExchangeNotComplete",
|
||||
"waitTime":10,
|
||||
"waitTimeRemaining":0,
|
||||
"timerRunning":false,
|
||||
"peerLdpId":""
|
||||
},
|
||||
"r2-eth2":{
|
||||
"state":"labelExchangeComplete",
|
||||
"waitTime":10,
|
||||
"waitTimeRemaining":0,
|
||||
"timerRunning":false,
|
||||
"peerLdpId":"3.3.3.3"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"r2-eth1":{
|
||||
"state":"labelExchangeComplete",
|
||||
"waitTime":10,
|
||||
"waitTimeRemaining":0,
|
||||
"timerRunning":false,
|
||||
"peerLdpId":"1.1.1.1"
|
||||
},
|
||||
"r2-eth2":{
|
||||
"state":"labelExchangeComplete",
|
||||
"waitTime":10,
|
||||
"waitTimeRemaining":0,
|
||||
"timerRunning":false,
|
||||
"peerLdpId":"3.3.3.3"
|
||||
}
|
||||
}
|
||||
16
tests/topotests/ldp-sync-isis-topo1/r2/show_ldp_neighbor.ref
Normal file
16
tests/topotests/ldp-sync-isis-topo1/r2/show_ldp_neighbor.ref
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"neighbors":[
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"neighborId":"1.1.1.1",
|
||||
"state":"OPERATIONAL",
|
||||
"transportAddress":"1.1.1.1"
|
||||
},
|
||||
{
|
||||
"addressFamily":"ipv4",
|
||||
"neighborId":"3.3.3.3",
|
||||
"state":"OPERATIONAL",
|
||||
"transportAddress":"3.3.3.3"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
{
|
||||
"frr-interface:lib": {
|
||||
"interface": [
|
||||
{
|
||||
"name": "r2-eth1",
|
||||
"vrf": "default",
|
||||
"state": {
|
||||
"frr-isisd:isis": {
|
||||
"adjacencies": {
|
||||
"adjacency": [
|
||||
{
|
||||
"neighbor-sys-type": "level-1",
|
||||
"neighbor-sysid": "0000.0000.0001",
|
||||
"neighbor-extended-circuit-id": 0,
|
||||
"state": "up"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "r2-eth2",
|
||||
"vrf": "default",
|
||||
"state": {
|
||||
"frr-isisd:isis": {
|
||||
"adjacencies": {
|
||||
"adjacency": [
|
||||
{
|
||||
"neighbor-sys-type": "level-1",
|
||||
"neighbor-sysid": "0000.0000.0003",
|
||||
"neighbor-extended-circuit-id": 0,
|
||||
"state": "up"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
28
tests/topotests/ldp-sync-isis-topo1/r2/zebra.conf
Normal file
28
tests/topotests/ldp-sync-isis-topo1/r2/zebra.conf
Normal file
@ -0,0 +1,28 @@
|
||||
log file zebra.log
|
||||
!
|
||||
hostname r2
|
||||
!
|
||||
debug zebra rib detailed
|
||||
debug zebra dplane detailed
|
||||
debug zebra kernel
|
||||
debug zebra nht
|
||||
debug zebra pseudowires
|
||||
!
|
||||
interface lo
|
||||
ip address 2.2.2.2/32
|
||||
!
|
||||
interface r2-eth0
|
||||
description to s2
|
||||
!
|
||||
interface r2-eth1
|
||||
description to s4
|
||||
ip address 10.0.1.2/24
|
||||
!
|
||||
interface r2-eth2
|
||||
description to s6
|
||||
ip address 10.0.3.2/24
|
||||
!
|
||||
ip forwarding
|
||||
!
|
||||
line vty
|
||||
!
|
||||
28
tests/topotests/ldp-sync-isis-topo1/r3/isisd.conf
Normal file
28
tests/topotests/ldp-sync-isis-topo1/r3/isisd.conf
Normal file
@ -0,0 +1,28 @@
|
||||
hostname r3
|
||||
log file isisd.log
|
||||
debug isis adj-packets
|
||||
debug isis events
|
||||
debug isis update-packets
|
||||
debug isis ldp-sync
|
||||
!
|
||||
router isis 1
|
||||
net 10.0000.0000.0000.0000.0000.0000.0000.0000.0003.00
|
||||
metric-style wide
|
||||
redistribute ipv4 connected level-1
|
||||
redistribute ipv6 connected level-1
|
||||
mpls ldp-sync
|
||||
mpls ldp-sync holddown 50
|
||||
!
|
||||
interface r3-eth1
|
||||
ip router isis 1
|
||||
ipv6 router isis 1
|
||||
isis network point-to-point
|
||||
isis circuit-type level-1
|
||||
no isis mpls ldp-sync
|
||||
!
|
||||
interface r3-eth2
|
||||
ip router isis 1
|
||||
ipv6 router isis 1
|
||||
isis network point-to-point
|
||||
isis circuit-type level-1
|
||||
!
|
||||
25
tests/topotests/ldp-sync-isis-topo1/r3/ldpd.conf
Normal file
25
tests/topotests/ldp-sync-isis-topo1/r3/ldpd.conf
Normal file
@ -0,0 +1,25 @@
|
||||
hostname r3
|
||||
log file ldpd.log
|
||||
!
|
||||
debug mpls ldp zebra
|
||||
debug mpls ldp event
|
||||
debug mpls ldp errors
|
||||
debug mpls ldp sync
|
||||
!
|
||||
mpls ldp
|
||||
router-id 3.3.3.3
|
||||
!
|
||||
address-family ipv4
|
||||
discovery transport-address 3.3.3.3
|
||||
label local allocate host-routes
|
||||
!
|
||||
ttl-security disable
|
||||
!
|
||||
interface r3-eth1
|
||||
!
|
||||
interface r3-eth2
|
||||
!
|
||||
!
|
||||
!
|
||||
line vty
|
||||
!
|
||||
143
tests/topotests/ldp-sync-isis-topo1/r3/show_ip_route.ref
Normal file
143
tests/topotests/ldp-sync-isis-topo1/r3/show_ip_route.ref
Normal file
@ -0,0 +1,143 @@
|
||||
{
|
||||
"1.1.1.1\/32":[
|
||||
{
|
||||
"prefix":"1.1.1.1\/32",
|
||||
"protocol":"isis",
|
||||
"selected":true,
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.2.1",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r3-eth1",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"2.2.2.2\/32":[
|
||||
{
|
||||
"prefix":"2.2.2.2\/32",
|
||||
"protocol":"isis",
|
||||
"selected":true,
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.3.2",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r3-eth2",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"3.3.3.3\/32":[
|
||||
{
|
||||
"prefix":"3.3.3.3\/32",
|
||||
"protocol":"connected",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"directlyConnected":true,
|
||||
"interfaceIndex":1,
|
||||
"interfaceName":"lo",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"10.0.1.0\/24":[
|
||||
{
|
||||
"prefix":"10.0.1.0\/24",
|
||||
"protocol":"isis",
|
||||
"selected":true,
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.2.1",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r3-eth1",
|
||||
"active":true
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"10.0.3.2",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r3-eth2",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"10.0.2.0\/24":[
|
||||
{
|
||||
"prefix":"10.0.2.0\/24",
|
||||
"protocol":"isis",
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"10.0.2.1",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r3-eth1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"prefix":"10.0.2.0\/24",
|
||||
"protocol":"connected",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"directlyConnected":true,
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r3-eth1",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"10.0.3.0\/24":[
|
||||
{
|
||||
"prefix":"10.0.3.0\/24",
|
||||
"protocol":"isis",
|
||||
"distance":115,
|
||||
"metric":10,
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"10.0.3.2",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r3-eth2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"prefix":"10.0.3.0\/24",
|
||||
"protocol":"connected",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"directlyConnected":true,
|
||||
"interfaceIndex":4,
|
||||
"interfaceName":"r3-eth2",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"1": {
|
||||
"r3-eth1": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
],
|
||||
"r3-eth2": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"1": {
|
||||
"r3-eth1": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
],
|
||||
"r3-eth2": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"1": {
|
||||
"r3-eth1": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
],
|
||||
"r3-eth2": [
|
||||
{
|
||||
"level": "Level-1",
|
||||
"metric": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
"r3-eth1":{
|
||||
"ldpIgpSyncEnabled":false,
|
||||
"holdDownTimeInSec":50,
|
||||
"ldpIgpSyncState":"Sync not required"
|
||||
},
|
||||
"r3-eth2":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":50,
|
||||
"ldpIgpSyncState":"Sync achieved"
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
"r3-eth1":{
|
||||
"ldpIgpSyncEnabled":false,
|
||||
"holdDownTimeInSec":50,
|
||||
"ldpIgpSyncState":"Sync not required"
|
||||
},
|
||||
"r3-eth2":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":50,
|
||||
"ldpIgpSyncState":"Sync achieved"
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
"r3-eth1":{
|
||||
"ldpIgpSyncEnabled":false,
|
||||
"holdDownTimeInSec":50,
|
||||
"ldpIgpSyncState":"Sync not required"
|
||||
},
|
||||
"r3-eth2":{
|
||||
"ldpIgpSyncEnabled":true,
|
||||
"holdDownTimeInSec":50,
|
||||
"ldpIgpSyncState":"Sync achieved"
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
2
tests/topotests/ldp-sync-isis-topo1/r3/show_l2vpn_vc.ref
Normal file
2
tests/topotests/ldp-sync-isis-topo1/r3/show_l2vpn_vc.ref
Normal file
@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user