mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 19:39:28 +00:00
ospf6d: allow configuring PtP neighbors & cost
Add a list of configured neighbors for each interface. Only stores cost (and "existence") for now. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
73940e52f2
commit
65e955890c
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
DECLARE_MTYPE(OSPF6_AUTH_MANUAL_KEY);
|
DECLARE_MTYPE(OSPF6_AUTH_MANUAL_KEY);
|
||||||
|
|
||||||
|
#include "ospf6_neighbor.h"
|
||||||
|
|
||||||
/* Debug option */
|
/* Debug option */
|
||||||
extern unsigned char conf_debug_ospf6_interface;
|
extern unsigned char conf_debug_ospf6_interface;
|
||||||
#define OSPF6_DEBUG_INTERFACE_ON() (conf_debug_ospf6_interface = 1)
|
#define OSPF6_DEBUG_INTERFACE_ON() (conf_debug_ospf6_interface = 1)
|
||||||
@ -66,6 +68,10 @@ struct ospf6_interface {
|
|||||||
uint8_t type;
|
uint8_t type;
|
||||||
bool type_cfg;
|
bool type_cfg;
|
||||||
|
|
||||||
|
/* P2P/P2MP behavior: */
|
||||||
|
|
||||||
|
struct ospf6_if_p2xp_neighcfgs_head p2xp_neighs;
|
||||||
|
|
||||||
/* Router Priority */
|
/* Router Priority */
|
||||||
uint8_t priority;
|
uint8_t priority;
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ void ospf6_router_lsa_originate(struct event *thread)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
|
lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
|
||||||
lsdesc->metric = htons(oi->cost);
|
lsdesc->metric = htons(ospf6_neighbor_cost(on));
|
||||||
lsdesc->interface_id =
|
lsdesc->interface_id =
|
||||||
htonl(oi->interface->ifindex);
|
htonl(oi->interface->ifindex);
|
||||||
lsdesc->neighbor_interface_id =
|
lsdesc->neighbor_interface_id =
|
||||||
|
@ -34,6 +34,18 @@
|
|||||||
#include "lib/json.h"
|
#include "lib/json.h"
|
||||||
|
|
||||||
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor");
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor");
|
||||||
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_NEIGHBOR_P2XP_CFG,
|
||||||
|
"OSPF6 PtP/PtMP neighbor config");
|
||||||
|
|
||||||
|
static int ospf6_if_p2xp_neighcfg_cmp(const struct ospf6_if_p2xp_neighcfg *a,
|
||||||
|
const struct ospf6_if_p2xp_neighcfg *b);
|
||||||
|
static struct ospf6_if_p2xp_neighcfg *
|
||||||
|
ospf6_if_p2xp_find(struct ospf6_interface *oi, const struct in6_addr *addr);
|
||||||
|
|
||||||
|
DECLARE_RBTREE_UNIQ(ospf6_if_p2xp_neighcfgs, struct ospf6_if_p2xp_neighcfg,
|
||||||
|
item, ospf6_if_p2xp_neighcfg_cmp);
|
||||||
|
|
||||||
|
static void p2xp_neigh_refresh(struct ospf6_neighbor *on, uint32_t prev_cost);
|
||||||
|
|
||||||
DEFINE_HOOK(ospf6_neighbor_change,
|
DEFINE_HOOK(ospf6_neighbor_change,
|
||||||
(struct ospf6_neighbor * on, int state, int next_state),
|
(struct ospf6_neighbor * on, int state, int next_state),
|
||||||
@ -150,6 +162,9 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id,
|
|||||||
|
|
||||||
void ospf6_neighbor_delete(struct ospf6_neighbor *on)
|
void ospf6_neighbor_delete(struct ospf6_neighbor *on)
|
||||||
{
|
{
|
||||||
|
if (on->p2xp_cfg)
|
||||||
|
on->p2xp_cfg->active = NULL;
|
||||||
|
|
||||||
ospf6_neighbor_clear_ls_lists(on);
|
ospf6_neighbor_clear_ls_lists(on);
|
||||||
|
|
||||||
ospf6_lsdb_remove_all(on->dbdesc_list);
|
ospf6_lsdb_remove_all(on->dbdesc_list);
|
||||||
@ -189,6 +204,12 @@ void ospf6_neighbor_lladdr_set(struct ospf6_neighbor *on,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(&on->linklocal_addr, addr, sizeof(struct in6_addr));
|
memcpy(&on->linklocal_addr, addr, sizeof(struct in6_addr));
|
||||||
|
|
||||||
|
if (on->ospf6_if->type == OSPF_IFTYPE_POINTOPOINT) {
|
||||||
|
uint32_t prev_cost = ospf6_neighbor_cost(on);
|
||||||
|
|
||||||
|
p2xp_neigh_refresh(on, prev_cost);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ospf6_neighbor_state_change(uint8_t next_state,
|
static void ospf6_neighbor_state_change(uint8_t next_state,
|
||||||
@ -616,8 +637,167 @@ void inactivity_timer(struct event *thread)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* P2P/P2MP stuff */
|
||||||
|
|
||||||
|
uint32_t ospf6_neighbor_cost(struct ospf6_neighbor *on)
|
||||||
|
{
|
||||||
|
if (on->p2xp_cfg && on->p2xp_cfg->cfg_cost)
|
||||||
|
return on->p2xp_cfg->cost;
|
||||||
|
return on->ospf6_if->cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ospf6_if_p2xp_neighcfg_cmp(const struct ospf6_if_p2xp_neighcfg *a,
|
||||||
|
const struct ospf6_if_p2xp_neighcfg *b)
|
||||||
|
{
|
||||||
|
return IPV6_ADDR_CMP(&a->addr, &b->addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ospf6_if_p2xp_neighcfg *
|
||||||
|
ospf6_if_p2xp_find(struct ospf6_interface *oi, const struct in6_addr *addr)
|
||||||
|
{
|
||||||
|
struct ospf6_if_p2xp_neighcfg ref;
|
||||||
|
|
||||||
|
if (!oi)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ref.addr = *addr;
|
||||||
|
return ospf6_if_p2xp_neighcfgs_find(&oi->p2xp_neighs, &ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ospf6_if_p2xp_neighcfg *
|
||||||
|
ospf6_if_p2xp_get(struct ospf6_interface *oi, const struct in6_addr *addr)
|
||||||
|
{
|
||||||
|
struct ospf6_if_p2xp_neighcfg ref, *ret;
|
||||||
|
|
||||||
|
if (!oi)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ref.addr = *addr;
|
||||||
|
ret = ospf6_if_p2xp_neighcfgs_find(&oi->p2xp_neighs, &ref);
|
||||||
|
if (!ret) {
|
||||||
|
ret = XCALLOC(MTYPE_OSPF6_NEIGHBOR_P2XP_CFG, sizeof(*ret));
|
||||||
|
ret->addr = *addr;
|
||||||
|
ret->ospf6_if = oi;
|
||||||
|
|
||||||
|
ospf6_if_p2xp_neighcfgs_add(&oi->p2xp_neighs, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ospf6_if_p2xp_destroy(struct ospf6_if_p2xp_neighcfg *p2xp_cfg)
|
||||||
|
{
|
||||||
|
EVENT_OFF(p2xp_cfg->t_unicast_hello);
|
||||||
|
ospf6_if_p2xp_neighcfgs_del(&p2xp_cfg->ospf6_if->p2xp_neighs, p2xp_cfg);
|
||||||
|
|
||||||
|
XFREE(MTYPE_OSPF6_NEIGHBOR_P2XP_CFG, p2xp_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void p2xp_neigh_refresh(struct ospf6_neighbor *on, uint32_t prev_cost)
|
||||||
|
{
|
||||||
|
if (on->p2xp_cfg)
|
||||||
|
on->p2xp_cfg->active = NULL;
|
||||||
|
on->p2xp_cfg = ospf6_if_p2xp_find(on->ospf6_if, &on->linklocal_addr);
|
||||||
|
if (on->p2xp_cfg)
|
||||||
|
on->p2xp_cfg->active = on;
|
||||||
|
|
||||||
|
if (ospf6_neighbor_cost(on) != prev_cost)
|
||||||
|
OSPF6_ROUTER_LSA_SCHEDULE(on->ospf6_if->area);
|
||||||
|
}
|
||||||
|
|
||||||
/* vty functions */
|
/* vty functions */
|
||||||
|
|
||||||
|
#ifndef VTYSH_EXTRACT_PL
|
||||||
|
#include "ospf6d/ospf6_neighbor_clippy.c"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DEFPY (ipv6_ospf6_p2xp_neigh,
|
||||||
|
ipv6_ospf6_p2xp_neigh_cmd,
|
||||||
|
"[no] ipv6 ospf6 neighbor X:X::X:X",
|
||||||
|
NO_STR
|
||||||
|
IP6_STR
|
||||||
|
OSPF6_STR
|
||||||
|
"Configure static neighbor\n"
|
||||||
|
"Neighbor link-local address\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||||
|
struct ospf6_interface *oi = ifp->info;
|
||||||
|
struct ospf6_if_p2xp_neighcfg *p2xp_cfg;
|
||||||
|
|
||||||
|
if (!oi) {
|
||||||
|
if (no)
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
oi = ospf6_interface_create(ifp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no) {
|
||||||
|
struct ospf6_neighbor *on;
|
||||||
|
uint32_t prev_cost = 0;
|
||||||
|
|
||||||
|
p2xp_cfg = ospf6_if_p2xp_find(oi, &neighbor);
|
||||||
|
if (!p2xp_cfg)
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
|
||||||
|
on = p2xp_cfg->active;
|
||||||
|
if (on)
|
||||||
|
prev_cost = ospf6_neighbor_cost(on);
|
||||||
|
|
||||||
|
p2xp_cfg->active = NULL;
|
||||||
|
ospf6_if_p2xp_destroy(p2xp_cfg);
|
||||||
|
|
||||||
|
if (on) {
|
||||||
|
on->p2xp_cfg = NULL;
|
||||||
|
p2xp_neigh_refresh(on, prev_cost);
|
||||||
|
}
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
p2xp_cfg = ospf6_if_p2xp_get(oi, &neighbor);
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFPY (ipv6_ospf6_p2xp_neigh_cost,
|
||||||
|
ipv6_ospf6_p2xp_neigh_cost_cmd,
|
||||||
|
"[no] ipv6 ospf6 neighbor X:X::X:X cost (1-65535)",
|
||||||
|
NO_STR
|
||||||
|
IP6_STR
|
||||||
|
OSPF6_STR
|
||||||
|
"Configure static neighbor\n"
|
||||||
|
"Neighbor link-local address\n"
|
||||||
|
"Outgoing metric for this neighbor\n"
|
||||||
|
"Outgoing metric for this neighbor\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||||
|
struct ospf6_interface *oi = ifp->info;
|
||||||
|
struct ospf6_if_p2xp_neighcfg *p2xp_cfg;
|
||||||
|
|
||||||
|
if (!oi) {
|
||||||
|
if (no)
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
oi = ospf6_interface_create(ifp);
|
||||||
|
}
|
||||||
|
|
||||||
|
p2xp_cfg = ospf6_if_p2xp_find(oi, &neighbor);
|
||||||
|
if (!p2xp_cfg)
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
|
||||||
|
uint32_t prev_cost;
|
||||||
|
if (p2xp_cfg->active)
|
||||||
|
prev_cost = ospf6_neighbor_cost(p2xp_cfg->active);
|
||||||
|
|
||||||
|
if (no) {
|
||||||
|
p2xp_cfg->cfg_cost = false;
|
||||||
|
p2xp_cfg->cost = 0;
|
||||||
|
} else {
|
||||||
|
p2xp_cfg->cfg_cost = true;
|
||||||
|
p2xp_cfg->cost = cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p2xp_cfg->active)
|
||||||
|
p2xp_neigh_refresh(p2xp_cfg->active, prev_cost);
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* show neighbor structure */
|
/* show neighbor structure */
|
||||||
static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on,
|
static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on,
|
||||||
json_object *json_array, bool use_json)
|
json_object *json_array, bool use_json)
|
||||||
@ -1223,6 +1403,9 @@ void ospf6_neighbor_init(void)
|
|||||||
{
|
{
|
||||||
install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_cmd);
|
install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_cmd);
|
||||||
install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_one_cmd);
|
install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_one_cmd);
|
||||||
|
|
||||||
|
install_element(INTERFACE_NODE, &ipv6_ospf6_p2xp_neigh_cmd);
|
||||||
|
install_element(INTERFACE_NODE, &ipv6_ospf6_p2xp_neigh_cost_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (debug_ospf6_neighbor,
|
DEFUN (debug_ospf6_neighbor,
|
||||||
@ -1325,6 +1508,21 @@ int config_write_ospf6_debug_neighbor(struct vty *vty)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int config_write_ospf6_p2xp_neighbor(struct vty *vty,
|
||||||
|
struct ospf6_interface *oi)
|
||||||
|
{
|
||||||
|
struct ospf6_if_p2xp_neighcfg *p2xp_cfg;
|
||||||
|
|
||||||
|
frr_each (ospf6_if_p2xp_neighcfgs, &oi->p2xp_neighs, p2xp_cfg) {
|
||||||
|
vty_out(vty, " ipv6 ospf6 neighbor %pI6\n", &p2xp_cfg->addr);
|
||||||
|
|
||||||
|
if (p2xp_cfg->cfg_cost)
|
||||||
|
vty_out(vty, " ipv6 ospf6 neighbor %pI6 cost %u\n",
|
||||||
|
&p2xp_cfg->addr, p2xp_cfg->cost);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void install_element_ospf6_debug_neighbor(void)
|
void install_element_ospf6_debug_neighbor(void)
|
||||||
{
|
{
|
||||||
install_element(ENABLE_NODE, &debug_ospf6_neighbor_cmd);
|
install_element(ENABLE_NODE, &debug_ospf6_neighbor_cmd);
|
||||||
|
@ -6,8 +6,11 @@
|
|||||||
#ifndef OSPF6_NEIGHBOR_H
|
#ifndef OSPF6_NEIGHBOR_H
|
||||||
#define OSPF6_NEIGHBOR_H
|
#define OSPF6_NEIGHBOR_H
|
||||||
|
|
||||||
|
#include "typesafe.h"
|
||||||
#include "hook.h"
|
#include "hook.h"
|
||||||
|
|
||||||
|
#include "ospf6_message.h"
|
||||||
|
|
||||||
/* Forward declaration(s). */
|
/* Forward declaration(s). */
|
||||||
struct ospf6_area;
|
struct ospf6_area;
|
||||||
|
|
||||||
@ -52,6 +55,8 @@ struct ospf6_helper_info {
|
|||||||
uint32_t rejected_reason;
|
uint32_t rejected_reason;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ospf6_if_p2xp_neighcfg;
|
||||||
|
|
||||||
/* Neighbor structure */
|
/* Neighbor structure */
|
||||||
struct ospf6_neighbor {
|
struct ospf6_neighbor {
|
||||||
/* Neighbor Router ID String */
|
/* Neighbor Router ID String */
|
||||||
@ -60,6 +65,11 @@ struct ospf6_neighbor {
|
|||||||
/* OSPFv3 Interface this neighbor belongs to */
|
/* OSPFv3 Interface this neighbor belongs to */
|
||||||
struct ospf6_interface *ospf6_if;
|
struct ospf6_interface *ospf6_if;
|
||||||
|
|
||||||
|
/* P2P/P2MP config for this neighbor.
|
||||||
|
* can be NULL if not explicitly configured!
|
||||||
|
*/
|
||||||
|
struct ospf6_if_p2xp_neighcfg *p2xp_cfg;
|
||||||
|
|
||||||
/* Neighbor state */
|
/* Neighbor state */
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
|
|
||||||
@ -140,6 +150,22 @@ struct ospf6_neighbor {
|
|||||||
bool lls_present;
|
bool lls_present;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PREDECL_RBTREE_UNIQ(ospf6_if_p2xp_neighcfgs);
|
||||||
|
|
||||||
|
struct ospf6_if_p2xp_neighcfg {
|
||||||
|
struct ospf6_if_p2xp_neighcfgs_item item;
|
||||||
|
|
||||||
|
struct ospf6_interface *ospf6_if;
|
||||||
|
struct in6_addr addr;
|
||||||
|
|
||||||
|
bool cfg_cost : 1;
|
||||||
|
|
||||||
|
uint32_t cost;
|
||||||
|
|
||||||
|
/* NULL if down */
|
||||||
|
struct ospf6_neighbor *active;
|
||||||
|
};
|
||||||
|
|
||||||
/* Neighbor state */
|
/* Neighbor state */
|
||||||
#define OSPF6_NEIGHBOR_DOWN 1
|
#define OSPF6_NEIGHBOR_DOWN 1
|
||||||
#define OSPF6_NEIGHBOR_ATTEMPT 2
|
#define OSPF6_NEIGHBOR_ATTEMPT 2
|
||||||
@ -193,6 +219,8 @@ void ospf6_neighbor_delete(struct ospf6_neighbor *on);
|
|||||||
void ospf6_neighbor_lladdr_set(struct ospf6_neighbor *on,
|
void ospf6_neighbor_lladdr_set(struct ospf6_neighbor *on,
|
||||||
const struct in6_addr *addr);
|
const struct in6_addr *addr);
|
||||||
|
|
||||||
|
uint32_t ospf6_neighbor_cost(struct ospf6_neighbor *on);
|
||||||
|
|
||||||
/* Neighbor event */
|
/* Neighbor event */
|
||||||
extern void hello_received(struct event *thread);
|
extern void hello_received(struct event *thread);
|
||||||
extern void twoway_received(struct event *thread);
|
extern void twoway_received(struct event *thread);
|
||||||
@ -208,6 +236,8 @@ extern void ospf6_check_nbr_loading(struct ospf6_neighbor *on);
|
|||||||
|
|
||||||
extern void ospf6_neighbor_init(void);
|
extern void ospf6_neighbor_init(void);
|
||||||
extern int config_write_ospf6_debug_neighbor(struct vty *vty);
|
extern int config_write_ospf6_debug_neighbor(struct vty *vty);
|
||||||
|
extern int config_write_ospf6_p2xp_neighbor(struct vty *vty,
|
||||||
|
struct ospf6_interface *oi);
|
||||||
extern void install_element_ospf6_debug_neighbor(void);
|
extern void install_element_ospf6_debug_neighbor(void);
|
||||||
|
|
||||||
DECLARE_HOOK(ospf6_neighbor_change,
|
DECLARE_HOOK(ospf6_neighbor_change,
|
||||||
|
@ -85,6 +85,7 @@ clippy_scan += \
|
|||||||
ospf6d/ospf6_gr.c \
|
ospf6d/ospf6_gr.c \
|
||||||
ospf6d/ospf6_nssa.c \
|
ospf6d/ospf6_nssa.c \
|
||||||
ospf6d/ospf6_route.c \
|
ospf6d/ospf6_route.c \
|
||||||
|
ospf6d/ospf6_neighbor.c \
|
||||||
# end
|
# end
|
||||||
|
|
||||||
nodist_ospf6d_ospf6d_SOURCES = \
|
nodist_ospf6d_ospf6d_SOURCES = \
|
||||||
|
Loading…
Reference in New Issue
Block a user