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:
David Lamparter 2021-07-20 15:57:18 +02:00 committed by Adriano Marto Reis
parent 73940e52f2
commit 65e955890c
5 changed files with 236 additions and 1 deletions

View File

@ -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;

View File

@ -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 =

View File

@ -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);

View File

@ -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,

View File

@ -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 = \