diff options
author | David Lamparter <equinox@opensourcerouting.org> | 2021-07-20 15:57:18 +0200 |
---|---|---|
committer | Adriano Marto Reis <adrianomarto@gmail.com> | 2023-10-09 23:57:43 +0200 |
commit | 65e955890c56e0652c702f9f1d7871adbd7f5ebf (patch) | |
tree | b1815367124fef0a456bf1948671ec0fb08f7e70 /ospf6d | |
parent | ospf6d: factor out link-local addr change (diff) | |
download | frr-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.h | 6 | ||||
-rw-r--r-- | ospf6d/ospf6_intra.c | 2 | ||||
-rw-r--r-- | ospf6d/ospf6_neighbor.c | 198 | ||||
-rw-r--r-- | ospf6d/ospf6_neighbor.h | 30 | ||||
-rw-r--r-- | ospf6d/subdir.am | 1 |
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 = \ |