summaryrefslogtreecommitdiffstats
path: root/ospf6d
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2021-07-20 15:57:18 +0200
committerAdriano Marto Reis <adrianomarto@gmail.com>2023-10-09 23:57:43 +0200
commit65e955890c56e0652c702f9f1d7871adbd7f5ebf (patch)
treeb1815367124fef0a456bf1948671ec0fb08f7e70 /ospf6d
parentospf6d: factor out link-local addr change (diff)
downloadfrr-65e955890c56e0652c702f9f1d7871adbd7f5ebf.tar.xz
frr-65e955890c56e0652c702f9f1d7871adbd7f5ebf.zip
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>
Diffstat (limited to 'ospf6d')
-rw-r--r--ospf6d/ospf6_interface.h6
-rw-r--r--ospf6d/ospf6_intra.c2
-rw-r--r--ospf6d/ospf6_neighbor.c198
-rw-r--r--ospf6d/ospf6_neighbor.h30
-rw-r--r--ospf6d/subdir.am1
5 files changed, 236 insertions, 1 deletions
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index 5942df0ab..2c01a6a51 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -13,6 +13,8 @@
DECLARE_MTYPE(OSPF6_AUTH_MANUAL_KEY);
+#include "ospf6_neighbor.h"
+
/* Debug option */
extern unsigned char conf_debug_ospf6_interface;
#define OSPF6_DEBUG_INTERFACE_ON() (conf_debug_ospf6_interface = 1)
@@ -66,6 +68,10 @@ struct ospf6_interface {
uint8_t type;
bool type_cfg;
+ /* P2P/P2MP behavior: */
+
+ struct ospf6_if_p2xp_neighcfgs_head p2xp_neighs;
+
/* Router Priority */
uint8_t priority;
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index eb5514adf..0b373505a 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -327,7 +327,7 @@ void ospf6_router_lsa_originate(struct event *thread)
continue;
lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
- lsdesc->metric = htons(oi->cost);
+ lsdesc->metric = htons(ospf6_neighbor_cost(on));
lsdesc->interface_id =
htonl(oi->interface->ifindex);
lsdesc->neighbor_interface_id =
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index d7d0d305f..78c0f43e5 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -34,6 +34,18 @@
#include "lib/json.h"
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,
(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)
{
+ if (on->p2xp_cfg)
+ on->p2xp_cfg->active = NULL;
+
ospf6_neighbor_clear_ls_lists(on);
ospf6_lsdb_remove_all(on->dbdesc_list);
@@ -189,6 +204,12 @@ void ospf6_neighbor_lladdr_set(struct ospf6_neighbor *on,
return;
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,
@@ -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 */
+
+#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 */
static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on,
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_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,
@@ -1325,6 +1508,21 @@ int config_write_ospf6_debug_neighbor(struct vty *vty)
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)
{
install_element(ENABLE_NODE, &debug_ospf6_neighbor_cmd);
diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h
index f8bab6dc9..c6d81006e 100644
--- a/ospf6d/ospf6_neighbor.h
+++ b/ospf6d/ospf6_neighbor.h
@@ -6,8 +6,11 @@
#ifndef OSPF6_NEIGHBOR_H
#define OSPF6_NEIGHBOR_H
+#include "typesafe.h"
#include "hook.h"
+#include "ospf6_message.h"
+
/* Forward declaration(s). */
struct ospf6_area;
@@ -52,6 +55,8 @@ struct ospf6_helper_info {
uint32_t rejected_reason;
};
+struct ospf6_if_p2xp_neighcfg;
+
/* Neighbor structure */
struct ospf6_neighbor {
/* Neighbor Router ID String */
@@ -60,6 +65,11 @@ struct ospf6_neighbor {
/* OSPFv3 Interface this neighbor belongs to */
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 */
uint8_t state;
@@ -140,6 +150,22 @@ struct ospf6_neighbor {
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 */
#define OSPF6_NEIGHBOR_DOWN 1
#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,
const struct in6_addr *addr);
+uint32_t ospf6_neighbor_cost(struct ospf6_neighbor *on);
+
/* Neighbor event */
extern void hello_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 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);
DECLARE_HOOK(ospf6_neighbor_change,
diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am
index f6d27c84c..24def6c5b 100644
--- a/ospf6d/subdir.am
+++ b/ospf6d/subdir.am
@@ -85,6 +85,7 @@ clippy_scan += \
ospf6d/ospf6_gr.c \
ospf6d/ospf6_nssa.c \
ospf6d/ospf6_route.c \
+ ospf6d/ospf6_neighbor.c \
# end
nodist_ospf6d_ospf6d_SOURCES = \