summaryrefslogtreecommitdiffstats
path: root/ospfd
diff options
context:
space:
mode:
authorDonatas Abraitis <donatas@opensourcerouting.org>2023-07-21 09:14:22 +0200
committerGitHub <noreply@github.com>2023-07-21 09:14:22 +0200
commit3a58764e3a7a5912187d5d062e06044bc1cd7044 (patch)
treeafeda04df0af66d136cfd53e3d7a83f7f5a92aa0 /ospfd
parentMerge pull request #14066 from opensourcerouting/fix/libyang_2.1.80 (diff)
parentospfd: Implement OSPF prefix-suppression as specified in RFC 6860 (diff)
downloadfrr-3a58764e3a7a5912187d5d062e06044bc1cd7044.tar.xz
frr-3a58764e3a7a5912187d5d062e06044bc1cd7044.zip
Merge pull request #14034 from LabNConsulting/aceelindem/ospf_prefix_suppression
ospfd: Implement OSPF prefix-suppression as specified in RFC 6860
Diffstat (limited to 'ospfd')
-rw-r--r--ospfd/ospf_interface.c3
-rw-r--r--ospfd/ospf_interface.h3
-rw-r--r--ospfd/ospf_lsa.c72
-rw-r--r--ospfd/ospf_route.c6
-rw-r--r--ospfd/ospf_vty.c83
5 files changed, 146 insertions, 21 deletions
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 72de19811..bdab672b4 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -600,6 +600,7 @@ void ospf_free_if_params(struct interface *ifp, struct in_addr addr)
!OSPF_IF_PARAM_CONFIGURED(oip, auth_type) &&
!OSPF_IF_PARAM_CONFIGURED(oip, if_area) &&
!OSPF_IF_PARAM_CONFIGURED(oip, opaque_capable) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, prefix_suppression) &&
listcount(oip->auth_crypt) == 0) {
ospf_del_if_params(ifp, oip);
rn->info = NULL;
@@ -709,6 +710,8 @@ int ospf_if_new_hook(struct interface *ifp)
SET_IF_PARAM(IF_DEF_PARAMS(ifp), opaque_capable);
IF_DEF_PARAMS(ifp)->opaque_capable = OSPF_OPAQUE_CAPABLE_DEFAULT;
+ IF_DEF_PARAMS(ifp)->prefix_suppression = OSPF_PREFIX_SUPPRESSION_DEFAULT;
+
rc = ospf_opaque_new_if(ifp);
return rc;
}
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index 38ec45c75..47b70f803 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -81,6 +81,9 @@ struct ospf_if_params {
/* Fast-Hellos */
DECLARE_IF_PARAM(uint8_t, fast_hello);
+ /* Prefix-Suppression */
+ DECLARE_IF_PARAM(bool, prefix_suppression);
+
/* Authentication data. */
uint8_t auth_simple[OSPF_AUTH_SIMPLE_SIZE + 1]; /* Simple password. */
uint8_t auth_simple__config : 1;
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 27e7e0275..7ef983427 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -539,16 +539,23 @@ static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
}
/* no need for a stub link for unnumbered interfaces */
- if (oi->ptp_dmvpn
- || !CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) {
- /* Regardless of the state of the neighboring router, we must
- add a Type 3 link (stub network).
- N.B. Options 1 & 2 share basically the same logic. */
- masklen2ip(oi->address->prefixlen, &mask);
- id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr
- & mask.s_addr;
- links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0,
- oi->output_cost);
+ if (OSPF_IF_PARAM(oi, prefix_suppression)) {
+ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
+ zlog_debug("LSA[Type1]: Interface %s stub link omitted due prefix-suppression",
+ oi->ifp->name);
+ } else {
+ if (oi->ptp_dmvpn ||
+ !CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) {
+ /* Regardless of the state of the neighboring router, we must
+ add a Type 3 link (stub network).
+ N.B. Options 1 & 2 share basically the same logic. */
+ masklen2ip(oi->address->prefixlen, &mask);
+ id.s_addr =
+ CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr &
+ mask.s_addr;
+ links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB,
+ 0, oi->output_cost);
+ }
}
return links;
@@ -563,10 +570,15 @@ static int lsa_link_broadcast_set(struct stream **s, struct ospf_interface *oi)
/* Describe Type 3 Link. */
if (oi->state == ISM_Waiting) {
+ if (OSPF_IF_PARAM(oi, prefix_suppression)) {
+ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
+ zlog_debug("LSA[Type1]: Interface %s stub link omitted due prefix-suppression",
+ oi->ifp->name);
+ return 0;
+ }
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
- zlog_debug(
- "LSA[Type1]: Interface %s is in state Waiting. Adding stub interface",
- oi->ifp->name);
+ zlog_debug("LSA[Type1]: Interface %s is in state Waiting. Adding stub interface",
+ oi->ifp->name);
masklen2ip(oi->address->prefixlen, &mask);
id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
return link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0,
@@ -587,10 +599,15 @@ static int lsa_link_broadcast_set(struct stream **s, struct ospf_interface *oi)
}
/* Describe type 3 link. */
else {
+ if (OSPF_IF_PARAM(oi, prefix_suppression)) {
+ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
+ zlog_debug("LSA[Type1]: Interface %s stub link omitted due prefix-suppression",
+ oi->ifp->name);
+ return 0;
+ }
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
- zlog_debug(
- "LSA[Type1]: Interface %s has no DR. Adding stub interface",
- oi->ifp->name);
+ zlog_debug("LSA[Type1]: Interface %s has no DR. Adding stub interface",
+ oi->ifp->name);
masklen2ip(oi->address->prefixlen, &mask);
id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
return link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0,
@@ -603,7 +620,7 @@ static int lsa_link_loopback_set(struct stream **s, struct ospf_interface *oi)
struct in_addr id, mask;
/* Describe Type 3 Link. */
- if (oi->state != ISM_Loopback)
+ if ((oi->state != ISM_Loopback) || OSPF_IF_PARAM(oi, prefix_suppression))
return 0;
mask.s_addr = 0xffffffff;
@@ -645,9 +662,15 @@ static int lsa_link_ptomp_set(struct stream **s, struct ospf_interface *oi)
struct in_addr id, mask;
uint16_t cost = ospf_link_cost(oi);
- mask.s_addr = 0xffffffff;
- id.s_addr = oi->address->u.prefix4.s_addr;
- links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, 0);
+ if (OSPF_IF_PARAM(oi, prefix_suppression)) {
+ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
+ zlog_debug("LSA[Type1]: Interface %s stub link omitted due prefix-suppression",
+ oi->ifp->name);
+ } else {
+ mask.s_addr = 0xffffffff;
+ id.s_addr = oi->address->u.prefix4.s_addr;
+ links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, 0);
+ }
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug("PointToMultipoint: running ptomultip_set");
@@ -1006,7 +1029,14 @@ static void ospf_network_lsa_body_set(struct stream *s,
struct route_node *rn;
struct ospf_neighbor *nbr;
- masklen2ip(oi->address->prefixlen, &mask);
+ if (OSPF_IF_PARAM(oi, prefix_suppression)) {
+ mask.s_addr = 0xffffffff;
+ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
+ zlog_debug("LSA[Type2]: Interface %s network mask set to host mask due prefix-suppression",
+ oi->ifp->name);
+ } else {
+ masklen2ip(oi->address->prefixlen, &mask);
+ }
stream_put_ipv4(s, mask.s_addr);
/* The network-LSA lists those routers that are fully adjacent to
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c
index 3ffa7c0bb..170909fa9 100644
--- a/ospfd/ospf_route.c
+++ b/ospfd/ospf_route.c
@@ -463,6 +463,12 @@ void ospf_intra_add_transit(struct route_table *rt, struct vertex *v,
the IP network number, which can be obtained by masking the
Vertex ID (Link State ID) with its associated subnet mask (found
in the body of the associated network-LSA). */
+ if (lsa->mask.s_addr == 0xffffffff) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("Suppress installing LSA[Type2,%pI4] route due to host mask",
+ &(lsa->header.id));
+ return;
+ }
p.family = AF_INET;
p.prefix = v->id;
p.prefixlen = ip_masklen(lsa->mask);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index a23802719..d3dbd4821 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -4076,6 +4076,20 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
ospf_interface_bfd_show(vty, ifp, json_interface_sub);
+ if (use_json) {
+ json_object_boolean_add(json_interface_sub,
+ "prefixSuppression",
+ OSPF_IF_PARAM(oi,
+ prefix_suppression));
+ json_object_boolean_add(json_oi, "prefixSuppression",
+ OSPF_IF_PARAM(oi,
+ prefix_suppression));
+ } else {
+ if (OSPF_IF_PARAM(oi, prefix_suppression))
+ vty_out(vty,
+ " Suppress advertisement of interface IP prefix\n");
+ }
+
/* OSPF Authentication information */
ospf_interface_auth_show(vty, oi, json_interface_sub, use_json);
@@ -9865,6 +9879,56 @@ DEFPY(ip_ospf_capability_opaque, ip_ospf_capability_opaque_addr_cmd,
}
+DEFPY(ip_ospf_prefix_suppression, ip_ospf_prefix_suppression_addr_cmd,
+ "[no] ip ospf prefix-suppression [A.B.C.D]$ip_addr", NO_STR
+ "IP Information\n"
+ "OSPF interface commands\n"
+ "Supress OSPF prefix advertisement on this interface\n"
+ "Address of interface\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct route_node *rn;
+ bool prefix_suppression_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);
+ }
+
+ prefix_suppression_change = (params->prefix_suppression == (bool)no);
+ params->prefix_suppression = (no) ? false : true;
+ if (params->prefix_suppression != OSPF_PREFIX_SUPPRESSION_DEFAULT)
+ SET_IF_PARAM(params, prefix_suppression);
+ else {
+ UNSET_IF_PARAM(params, prefix_suppression);
+ 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 prefix suppression, update the Router-LSA.
+ */
+ if (prefix_suppression_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))) {
+ (void)ospf_router_lsa_update_area(oi->area);
+ if (oi->state == ISM_DR)
+ ospf_network_lsa_update(oi);
+ }
+ }
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (ospf_max_metric_router_lsa_admin,
ospf_max_metric_router_lsa_admin_cmd,
"max-metric router-lsa administrative",
@@ -12285,6 +12349,22 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
vty_out(vty, "\n");
}
+ /* prefix-suppression print. */
+ if (OSPF_IF_PARAM_CONFIGURED(params,
+ prefix_suppression) &&
+ params->prefix_suppression !=
+ OSPF_PREFIX_SUPPRESSION_DEFAULT) {
+ if (params->prefix_suppression == false)
+ vty_out(vty,
+ " no ip ospf prefix-suppression");
+ else
+ vty_out(vty,
+ " ip ospf prefix-suppression");
+ 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));
@@ -13097,6 +13177,9 @@ static void ospf_vty_if_init(void)
/* "ip ospf capability opaque" commands. */
install_element(INTERFACE_NODE, &ip_ospf_capability_opaque_addr_cmd);
+ /* "ip ospf prefix-suppression" commands. */
+ install_element(INTERFACE_NODE, &ip_ospf_prefix_suppression_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);