summaryrefslogtreecommitdiff
path: root/ospfd
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2023-07-11 11:47:32 -0400
committerGitHub <noreply@github.com>2023-07-11 11:47:32 -0400
commit6e89a5db228c75d83f9be7b3606b91257e0307d3 (patch)
tree3d8e0dc9474ea768c653b4d7697cbf1fe5c07112 /ospfd
parentc8971388a9013ffb65b4de20fd1553f6e1e94311 (diff)
parente72549c8f6f7b25738f8d4c913db025a7906558e (diff)
Merge pull request #13691 from LabNConsulting/aceelindem/ospf-opaque-interface-disable
ospfd: Configurable interface-level 'capability opaque' support
Diffstat (limited to 'ospfd')
-rw-r--r--ospfd/ospf_flood.c9
-rw-r--r--ospfd/ospf_gr.c11
-rw-r--r--ospfd/ospf_interface.c32
-rw-r--r--ospfd/ospf_interface.h3
-rw-r--r--ospfd/ospf_opaque.c6
-rw-r--r--ospfd/ospf_packet.c16
-rw-r--r--ospfd/ospf_vty.c79
7 files changed, 132 insertions, 24 deletions
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 5ae15fd887..dd8c9268f1 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -568,6 +568,15 @@ int ospf_flood_through_interface(struct ospf_interface *oi,
if (!ospf_if_is_enable(oi))
return 0;
+ if (IS_OPAQUE_LSA(lsa->data->type) &&
+ !OSPF_IF_PARAM(oi, opaque_capable)) {
+ if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
+ zlog_debug(
+ "%s: Skipping interface %s (%s) with opaque disabled.",
+ __func__, IF_NAME(oi), ospf_get_name(oi->ospf));
+ return 0;
+ }
+
/* If flood reduction is configured, set the DC bit on the lsa. */
if (IS_LSA_SELF(lsa)) {
if (OSPF_FR_CONFIG(oi->area->ospf, oi->area)) {
diff --git a/ospfd/ospf_gr.c b/ospfd/ospf_gr.c
index 2a346f2388..c23c42052f 100644
--- a/ospfd/ospf_gr.c
+++ b/ospfd/ospf_gr.c
@@ -773,8 +773,15 @@ static void ospf_gr_prepare(void)
}
/* Send a Grace-LSA to all neighbors. */
- for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, inode, oi))
- ospf_gr_lsa_originate(oi, OSPF_GR_SW_RESTART, false);
+ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, inode, oi)) {
+ if (OSPF_IF_PARAM(oi, opaque_capable))
+ ospf_gr_lsa_originate(oi, OSPF_GR_SW_RESTART,
+ false);
+ else
+ zlog_debug(
+ "GR: skipping grace LSA on interface %s (%s) with opaque capability disabled",
+ IF_NAME(oi), ospf_get_name(oi->ospf));
+ }
/* Record end of the grace period in non-volatile memory. */
ospf_gr_nvm_update(ospf, true);
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 840756c05c..72de198116 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -548,6 +548,7 @@ static struct ospf_if_params *ospf_new_if_params(void)
UNSET_IF_PARAM(oip, auth_crypt);
UNSET_IF_PARAM(oip, auth_type);
UNSET_IF_PARAM(oip, if_area);
+ UNSET_IF_PARAM(oip, opaque_capable);
oip->auth_crypt = list_new();
@@ -556,6 +557,7 @@ static struct ospf_if_params *ospf_new_if_params(void)
oip->ptp_dmvpn = 0;
oip->p2mp_delay_reflood = OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
+ oip->opaque_capable = OSPF_OPAQUE_CAPABLE_DEFAULT;
return oip;
}
@@ -585,19 +587,20 @@ void ospf_free_if_params(struct interface *ifp, struct in_addr addr)
oip = rn->info;
route_unlock_node(rn);
- if (!OSPF_IF_PARAM_CONFIGURED(oip, output_cost_cmd)
- && !OSPF_IF_PARAM_CONFIGURED(oip, transmit_delay)
- && !OSPF_IF_PARAM_CONFIGURED(oip, retransmit_interval)
- && !OSPF_IF_PARAM_CONFIGURED(oip, passive_interface)
- && !OSPF_IF_PARAM_CONFIGURED(oip, v_hello)
- && !OSPF_IF_PARAM_CONFIGURED(oip, fast_hello)
- && !OSPF_IF_PARAM_CONFIGURED(oip, v_wait)
- && !OSPF_IF_PARAM_CONFIGURED(oip, priority)
- && !OSPF_IF_PARAM_CONFIGURED(oip, type)
- && !OSPF_IF_PARAM_CONFIGURED(oip, auth_simple)
- && !OSPF_IF_PARAM_CONFIGURED(oip, auth_type)
- && !OSPF_IF_PARAM_CONFIGURED(oip, if_area)
- && listcount(oip->auth_crypt) == 0) {
+ if (!OSPF_IF_PARAM_CONFIGURED(oip, output_cost_cmd) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, transmit_delay) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, retransmit_interval) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, passive_interface) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, v_hello) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, fast_hello) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, v_wait) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, priority) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, type) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, auth_simple) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, auth_type) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, if_area) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, opaque_capable) &&
+ listcount(oip->auth_crypt) == 0) {
ospf_del_if_params(ifp, oip);
rn->info = NULL;
route_unlock_node(rn);
@@ -703,6 +706,9 @@ int ospf_if_new_hook(struct interface *ifp)
SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_type);
IF_DEF_PARAMS(ifp)->auth_type = OSPF_AUTH_NOTSET;
+ SET_IF_PARAM(IF_DEF_PARAMS(ifp), opaque_capable);
+ IF_DEF_PARAMS(ifp)->opaque_capable = OSPF_OPAQUE_CAPABLE_DEFAULT;
+
rc = ospf_opaque_new_if(ifp);
return rc;
}
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index ec1afa1b8b..38ec45c757 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -112,6 +112,9 @@ struct ospf_if_params {
/* point-to-multipoint delayed reflooding configuration */
bool p2mp_delay_reflood;
+
+ /* Opaque LSA capability at interface level (see RFC5250) */
+ DECLARE_IF_PARAM(bool, opaque_capable);
};
enum { MEMBER_ALLROUTERS = 0,
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index 6894c6a009..27f47a6d79 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -1851,9 +1851,9 @@ static void ospf_opaque_type9_lsa_reoriginate_timer(struct event *t)
return;
}
- if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)
- || !ospf_if_is_enable(oi)
- || ospf_nbr_count_opaque_capable(oi) == 0) {
+ if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE) ||
+ !OSPF_IF_PARAM(oi, opaque_capable) || !ospf_if_is_enable(oi) ||
+ ospf_nbr_count_opaque_capable(oi) == 0) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 105c04c7a1..cfa0d5d574 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -953,8 +953,9 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh,
}
#endif /* REJECT_IF_TBIT_ON */
- if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)
- && CHECK_FLAG(hello->options, OSPF_OPTION_O)) {
+ if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) &&
+ OSPF_IF_PARAM(oi, opaque_capable) &&
+ CHECK_FLAG(hello->options, OSPF_OPTION_O)) {
/*
* This router does know the correct usage of O-bit
* the bit should be set in DD packet only.
@@ -1362,8 +1363,9 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh,
}
#endif /* REJECT_IF_TBIT_ON */
- if (CHECK_FLAG(dd->options, OSPF_OPTION_O)
- && !CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)) {
+ if (CHECK_FLAG(dd->options, OSPF_OPTION_O) &&
+ (!CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) ||
+ !OSPF_IF_PARAM(oi, opaque_capable))) {
/*
* This node is not configured to handle O-bit, for now.
* Clear it to ignore unsupported capability proposed by
@@ -1448,7 +1450,8 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh,
/* This is where the real Options are saved */
nbr->options = dd->options;
- if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)) {
+ if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) &&
+ OSPF_IF_PARAM(oi, opaque_capable)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"Neighbor[%pI4] is %sOpaque-capable.",
@@ -3435,7 +3438,8 @@ static int ospf_make_db_desc(struct ospf_interface *oi,
/* Set Options. */
options = OPTIONS(oi);
- if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE))
+ if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) &&
+ OSPF_IF_PARAM(oi, opaque_capable))
SET_FLAG(options, OSPF_OPTION_O);
if (OSPF_FR_CONFIG(oi->ospf, oi->area))
SET_FLAG(options, OSPF_OPTION_DC);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 863055bf42..54fd60af23 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -3811,6 +3811,9 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
lookup_msg(ospf_ism_state_msg,
oi->state, NULL));
json_object_int_add(json_oi, "priority", PRIORITY(oi));
+ json_object_boolean_add(
+ json_interface_sub, "opaqueCapable",
+ OSPF_IF_PARAM(oi, opaque_capable));
} else {
vty_out(vty, " Area %s\n",
ospf_area_desc_string(oi->area));
@@ -3830,6 +3833,9 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
OSPF_IF_PARAM(oi, transmit_delay),
lookup_msg(ospf_ism_state_msg, oi->state, NULL),
PRIORITY(oi));
+ if (!OSPF_IF_PARAM(oi, opaque_capable))
+ vty_out(vty,
+ " Opaque LSA capability disabled on interface\n");
}
/* Show DR information. */
@@ -9803,6 +9809,61 @@ DEFUN (no_ip_ospf_mtu_ignore,
return CMD_SUCCESS;
}
+DEFPY(ip_ospf_capability_opaque, ip_ospf_capability_opaque_addr_cmd,
+ "[no] ip ospf capability opaque [A.B.C.D]$ip_addr",
+ NO_STR
+ "IP Information\n"
+ "OSPF interface commands\n"
+ "Disable OSPF capability on this interface\n"
+ "Disable OSPF opaque LSA capability on this interface\n"
+ "Address of interface\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct route_node *rn;
+ bool old_opaque_capable;
+ bool opaque_capable_change;
+
+ struct ospf_if_params *params;
+ params = IF_DEF_PARAMS(ifp);
+
+ if (ip_addr.s_addr != INADDR_ANY) {
+ params = ospf_get_if_params(ifp, ip_addr);
+ ospf_if_update_params(ifp, ip_addr);
+ }
+
+ old_opaque_capable = params->opaque_capable;
+ params->opaque_capable = (no) ? false : true;
+ opaque_capable_change = (old_opaque_capable != params->opaque_capable);
+ if (params->opaque_capable != OSPF_OPAQUE_CAPABLE_DEFAULT)
+ SET_IF_PARAM(params, opaque_capable);
+ else {
+ UNSET_IF_PARAM(params, opaque_capable);
+ if (params != IF_DEF_PARAMS(ifp)) {
+ ospf_free_if_params(ifp, ip_addr);
+ ospf_if_update_params(ifp, ip_addr);
+ }
+ }
+
+ /*
+ * If there is a change to the opaque capability, flap the interface
+ * to reset all the neighbor adjacencies.
+ */
+ if (opaque_capable_change) {
+ for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
+ struct ospf_interface *oi = rn->info;
+
+ if (oi && (oi->state > ISM_Down) &&
+ (ip_addr.s_addr == INADDR_ANY ||
+ IPV4_ADDR_SAME(&oi->address->u.prefix4,
+ &ip_addr))) {
+ OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
+ OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp);
+ }
+ }
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (ospf_max_metric_router_lsa_admin,
ospf_max_metric_router_lsa_admin_cmd,
@@ -12167,6 +12228,21 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
if (params && params->ldp_sync_info)
ospf_ldp_sync_if_write_config(vty, params);
+ /* Capability opaque print. */
+ if (OSPF_IF_PARAM_CONFIGURED(params, opaque_capable) &&
+ params->opaque_capable !=
+ OSPF_OPAQUE_CAPABLE_DEFAULT) {
+ if (params->opaque_capable == false)
+ vty_out(vty,
+ " no ip ospf capability opaque");
+ else
+ vty_out(vty,
+ " ip ospf capability opaque");
+ if (params != IF_DEF_PARAMS(ifp) && rn)
+ vty_out(vty, " %pI4", &rn->p.u.prefix4);
+ vty_out(vty, "\n");
+ }
+
while (1) {
if (rn == NULL)
rn = route_top(IF_OIFS_PARAMS(ifp));
@@ -12976,6 +13052,9 @@ static void ospf_vty_if_init(void)
install_element(INTERFACE_NODE, &ip_ospf_passive_cmd);
install_element(INTERFACE_NODE, &no_ip_ospf_passive_cmd);
+ /* "ip ospf capability opaque" commands. */
+ install_element(INTERFACE_NODE, &ip_ospf_capability_opaque_addr_cmd);
+
/* These commands are compatibitliy for previous version. */
install_element(INTERFACE_NODE, &ospf_authentication_key_cmd);
install_element(INTERFACE_NODE, &ospf_message_digest_key_cmd);