ospf6d: add overload support
OSPFv3: Support setting/clearing overload bit on router
It is sometimes necessary for a router to gracefully remove itself from
the SPF tree i.e. it cannot act as a transit router. It does this by
setting the overload bit in the router LSA. This patch adds support for
enabling/disabling the overload bit.
Signed-off-by: Dinesh G Dutt <ddutt at cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat at cumulusnetworks.com>
[DL: patch applied with fuzz]
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 1e07d85..37e5c00 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -164,9 +164,18 @@
oa->summary_router->scope = oa;
/* set default options */
- OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
+ if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER))
+ {
+ OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6);
+ OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R);
+ }
+ else
+ {
+ OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
+ OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
+ }
+
OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
- OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
oa->ospf6 = o;
listnode_add_sort (o->area_list, oa);
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index c08a6ae..025a771 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -105,6 +105,29 @@
}
int
+ospf6_router_is_stub_router (struct ospf6_lsa *lsa)
+{
+ struct ospf6_router_lsa *rtr_lsa;
+
+ if (lsa != NULL && OSPF6_LSA_IS_TYPE (ROUTER, lsa))
+ {
+ rtr_lsa = (struct ospf6_router_lsa *)
+ ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
+
+ if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_R))
+ {
+ return (OSPF6_IS_STUB_ROUTER);
+ }
+ else if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_V6))
+ {
+ return (OSPF6_IS_STUB_ROUTER_V6);
+ }
+ }
+
+ return (OSPF6_NOT_STUB_ROUTER);
+}
+
+int
ospf6_router_lsa_originate (struct thread *thread)
{
struct ospf6_area *oa;
diff --git a/ospf6d/ospf6_intra.h b/ospf6d/ospf6_intra.h
index 3810174..a25efa1 100644
--- a/ospf6d/ospf6_intra.h
+++ b/ospf6d/ospf6_intra.h
@@ -94,6 +94,13 @@
#define OSPF6_ROUTER_LSDESC_STUB_NETWORK 3
#define OSPF6_ROUTER_LSDESC_VIRTUAL_LINK 4
+enum stub_router_mode
+ {
+ OSPF6_NOT_STUB_ROUTER,
+ OSPF6_IS_STUB_ROUTER,
+ OSPF6_IS_STUB_ROUTER_V6,
+ };
+
#define ROUTER_LSDESC_IS_TYPE(t,x) \
((((struct ospf6_router_lsdesc *)(x))->type == \
OSPF6_ROUTER_LSDESC_ ## t) ? 1 : 0)
@@ -200,6 +207,7 @@
extern char *ospf6_network_lsdesc_lookup (u_int32_t router_id,
struct ospf6_lsa *lsa);
+extern int ospf6_router_is_stub_router (struct ospf6_lsa *lsa);
extern int ospf6_router_lsa_originate (struct thread *);
extern int ospf6_network_lsa_originate (struct thread *);
extern int ospf6_link_lsa_originate (struct thread *);
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index e4c424d..845e206 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -424,6 +424,11 @@
if (ospf6_spf_install (v, result_table) < 0)
continue;
+ /* Skip overloaded routers */
+ if ((OSPF6_LSA_IS_TYPE (ROUTER, v->lsa) &&
+ ospf6_router_is_stub_router (v->lsa)))
+ continue;
+
/* For each LS description in the just-added vertex V's LSA */
size = (VERTEX_IS_TYPE (ROUTER, v) ?
sizeof (struct ospf6_router_lsdesc) :
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index e9fe7a4..dec7096 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -464,6 +464,101 @@
return CMD_SUCCESS;
}
+DEFUN (ospf6_stub_router_admin,
+ ospf6_stub_router_admin_cmd,
+ "stub-router administrative",
+ "Make router a stub router\n"
+ "Advertise inability to be a transit router\n"
+ "Administratively applied, for an indefinite period\n")
+{
+ struct listnode *node;
+ struct ospf6_area *oa;
+
+ if (!CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
+ {
+ for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
+ {
+ OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6);
+ OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R);
+ OSPF6_ROUTER_LSA_SCHEDULE (oa);
+ }
+ SET_FLAG (ospf6->flag, OSPF6_STUB_ROUTER);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_stub_router_admin,
+ no_ospf6_stub_router_admin_cmd,
+ "no stub-router administrative",
+ NO_STR
+ "Make router a stub router\n"
+ "Advertise ability to be a transit router\n"
+ "Administratively applied, for an indefinite period\n")
+{
+ struct listnode *node;
+ struct ospf6_area *oa;
+
+ if (CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
+ {
+ for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
+ {
+ OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
+ OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
+ OSPF6_ROUTER_LSA_SCHEDULE (oa);
+ }
+ UNSET_FLAG (ospf6->flag, OSPF6_STUB_ROUTER);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (ospf6_stub_router_startup,
+ ospf6_stub_router_startup_cmd,
+ "stub-router on-startup <5-86400>",
+ "Make router a stub router\n"
+ "Advertise inability to be a transit router\n"
+ "Automatically advertise as stub-router on startup of OSPF6\n"
+ "Time (seconds) to advertise self as stub-router\n")
+{
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_stub_router_startup,
+ no_ospf6_stub_router_startup_cmd,
+ "no stub-router on-startup",
+ NO_STR
+ "Make router a stub router\n"
+ "Advertise inability to be a transit router\n"
+ "Automatically advertise as stub-router on startup of OSPF6\n"
+ "Time (seconds) to advertise self as stub-router\n")
+{
+ return CMD_SUCCESS;
+}
+
+DEFUN (ospf6_stub_router_shutdown,
+ ospf6_stub_router_shutdown_cmd,
+ "stub-router on-shutdown <5-86400>",
+ "Make router a stub router\n"
+ "Advertise inability to be a transit router\n"
+ "Automatically advertise as stub-router before shutdown\n"
+ "Time (seconds) to advertise self as stub-router\n")
+{
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_stub_router_shutdown,
+ no_ospf6_stub_router_shutdown_cmd,
+ "no stub-router on-shutdown",
+ NO_STR
+ "Make router a stub router\n"
+ "Advertise inability to be a transit router\n"
+ "Automatically advertise as stub-router before shutdown\n"
+ "Time (seconds) to advertise self as stub-router\n")
+{
+ return CMD_SUCCESS;
+}
+
static void
ospf6_show (struct vty *vty, struct ospf6 *o)
{
@@ -486,6 +581,9 @@
/* Redistribute configuration */
/* XXX */
+ if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER))
+ vty_out (vty, " Router Is Stub Router%s", VNL);
+
/* LSAs */
vty_out (vty, " Number of AS scoped LSAs is %u%s",
o->lsdb->count, VNL);
@@ -654,6 +752,16 @@
return CMD_SUCCESS;
}
+static void
+ospf6_stub_router_config_write (struct vty *vty)
+{
+ if (CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
+ {
+ vty_out (vty, " stub-router administrative%s", VNL);
+ }
+ return;
+}
+
/* OSPF configuration write function. */
static int
config_write_ospf6 (struct vty *vty)
@@ -674,6 +782,7 @@
if (ospf6->router_id_static != 0)
vty_out (vty, " router-id %s%s", router_id, VNL);
+ ospf6_stub_router_config_write (vty);
ospf6_redistribute_config_write (vty);
ospf6_area_config_write (vty);
ospf6_spf_config_write (vty);
@@ -729,6 +838,14 @@
install_element (OSPF6_NODE, &ospf6_router_id_cmd);
install_element (OSPF6_NODE, &ospf6_interface_area_cmd);
install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd);
+ install_element (OSPF6_NODE, &ospf6_stub_router_admin_cmd);
+ install_element (OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
+ /* For a later time
+ install_element (OSPF6_NODE, &ospf6_stub_router_startup_cmd);
+ install_element (OSPF6_NODE, &no_ospf6_stub_router_startup_cmd);
+ install_element (OSPF6_NODE, &ospf6_stub_router_shutdown_cmd);
+ install_element (OSPF6_NODE, &no_ospf6_stub_router_shutdown_cmd);
+ */
}
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index 27eb18c..02eb915 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -76,6 +76,7 @@
};
#define OSPF6_DISABLED 0x01
+#define OSPF6_STUB_ROUTER 0x02
/* global pointer for OSPF top data structure */
extern struct ospf6 *ospf6;