summaryrefslogtreecommitdiff
path: root/ospf6d/ospf6_asbr.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospf6d/ospf6_asbr.c')
-rw-r--r--ospf6d/ospf6_asbr.c367
1 files changed, 281 insertions, 86 deletions
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 3497b26656..ffd6dc22c3 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -30,6 +30,7 @@
#include "plist.h"
#include "thread.h"
#include "linklist.h"
+#include "lib/northbound_cli.h"
#include "ospf6_proto.h"
#include "ospf6_lsa.h"
@@ -37,6 +38,7 @@
#include "ospf6_route.h"
#include "ospf6_zebra.h"
#include "ospf6_message.h"
+#include "ospf6_spf.h"
#include "ospf6_top.h"
#include "ospf6_area.h"
@@ -57,6 +59,10 @@ static void ospf6_asbr_redistribute_set(int type, vrf_id_t vrf_id);
static void ospf6_asbr_redistribute_unset(struct ospf6 *ospf6,
struct ospf6_redist *red, int type);
+#ifndef VTYSH_EXTRACT_PL
+#include "ospf6d/ospf6_asbr_clippy.c"
+#endif
+
unsigned char conf_debug_ospf6_asbr = 0;
#define ZROUTE_NAME(x) zebra_route_string(x)
@@ -1047,6 +1053,7 @@ static struct ospf6_redist *ospf6_redist_add(struct ospf6 *ospf6, int type,
ROUTEMAP(red) = NULL;
listnode_add(ospf6->redist[type], red);
+ ospf6->redistribute++;
return red;
}
@@ -1060,6 +1067,7 @@ static void ospf6_redist_del(struct ospf6 *ospf6, struct ospf6_redist *red,
list_delete(&ospf6->redist[type]);
}
XFREE(MTYPE_OSPF6_REDISTRIBUTE, red);
+ ospf6->redistribute--;
}
}
@@ -1096,8 +1104,10 @@ void ospf6_asbr_send_externals_to_area(struct ospf6_area *oa)
for (ALL_LSDB(oa->ospf6->lsdb, lsa, lsanext)) {
if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL) {
- zlog_debug("%s: Flooding AS-External LSA %s",
- __func__, lsa->name);
+ if (IS_OSPF6_DEBUG_ASBR)
+ zlog_debug("%s: Flooding AS-External LSA %s",
+ __func__, lsa->name);
+
ospf6_flood_area(NULL, lsa, oa);
}
}
@@ -1120,6 +1130,7 @@ void ospf6_asbr_remove_externals_from_area(struct ospf6_area *oa)
/* if router is only in a stub area then purge AS-External LSAs */
iterend = ospf6_lsdb_head(ospf6->lsdb, 0, 0, 0, &lsa);
while (lsa != NULL) {
+ assert(lsa->lock > 1);
lsanext = ospf6_lsdb_next(iterend, lsa);
if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL)
ospf6_lsdb_remove(lsa, ospf6->lsdb);
@@ -1127,6 +1138,35 @@ void ospf6_asbr_remove_externals_from_area(struct ospf6_area *oa)
}
}
+/* Update ASBR status. */
+static void ospf6_asbr_status_update(struct ospf6 *ospf6, uint8_t status)
+{
+ struct listnode *lnode, *lnnode;
+ struct ospf6_area *oa;
+
+ zlog_info("ASBR[%s:Status:%d]: Update", ospf6->name, status);
+
+ if (status) {
+ if (IS_OSPF6_ASBR(ospf6)) {
+ zlog_info("ASBR[%s:Status:%d]: Already ASBR",
+ ospf6->name, status);
+ return;
+ }
+ SET_FLAG(ospf6->flag, OSPF6_FLAG_ASBR);
+ } else {
+ if (!IS_OSPF6_ASBR(ospf6)) {
+ zlog_info("ASBR[%s:Status:%d]: Already non ASBR",
+ ospf6->name, status);
+ return;
+ }
+ UNSET_FLAG(ospf6->flag, OSPF6_FLAG_ASBR);
+ }
+
+ ospf6_spf_schedule(ospf6, OSPF6_SPF_FLAGS_ASBR_STATUS_CHANGE);
+ for (ALL_LIST_ELEMENTS(ospf6->area_list, lnode, lnnode, oa))
+ OSPF6_ROUTER_LSA_SCHEDULE(oa);
+}
+
void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
struct prefix *prefix,
unsigned int nexthop_num,
@@ -1141,8 +1181,6 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
struct prefix prefix_id;
struct route_node *node;
char ibuf[16];
- struct listnode *lnode, *lnnode;
- struct ospf6_area *oa;
struct ospf6_redist *red;
red = ospf6_redist_lookup(ospf6, type, 0);
@@ -1150,7 +1188,8 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
if (!red)
return;
- if (!ospf6_zebra_is_redistribute(type, ospf6->vrf_id))
+ if ((type != DEFAULT_ROUTE)
+ && !ospf6_zebra_is_redistribute(type, ospf6->vrf_id))
return;
memset(&troute, 0, sizeof(troute));
@@ -1203,7 +1242,11 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
sizeof(struct in6_addr));
info->tag = tinfo.tag;
} else {
- /* If there is no route-map, simply update the tag */
+ /* If there is no route-map, simply update the tag and
+ * metric fields
+ */
+ match->path.metric_type = metric_type(ospf6, type, 0);
+ match->path.cost = metric_value(ospf6, type, 0);
info->tag = tag;
}
@@ -1231,6 +1274,7 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
match->path.origin.id = htonl(info->id);
ospf6_as_external_lsa_originate(match, ospf6);
+ ospf6_asbr_status_update(ospf6, ospf6->redistribute);
return;
}
@@ -1255,7 +1299,11 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
sizeof(struct in6_addr));
info->tag = tinfo.tag;
} else {
- /* If there is no route-map, simply set the tag */
+ /* If there is no route-map, simply update the tag and metric
+ * fields
+ */
+ route->path.metric_type = metric_type(ospf6, type, 0);
+ route->path.cost = metric_value(ospf6, type, 0);
info->tag = tag;
}
@@ -1284,10 +1332,7 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
route->path.origin.id = htonl(info->id);
ospf6_as_external_lsa_originate(route, ospf6);
-
- /* Router-Bit (ASBR Flag) may have to be updated */
- for (ALL_LIST_ELEMENTS(ospf6->area_list, lnode, lnnode, oa))
- OSPF6_ROUTER_LSA_SCHEDULE(oa);
+ ospf6_asbr_status_update(ospf6, ospf6->redistribute);
}
void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex,
@@ -1299,8 +1344,6 @@ void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex,
struct ospf6_lsa *lsa;
struct prefix prefix_id;
char ibuf[16];
- struct listnode *lnode, *lnnode;
- struct ospf6_area *oa;
match = ospf6_route_lookup(prefix, ospf6->external_table);
if (match == NULL) {
@@ -1341,9 +1384,7 @@ void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex,
ospf6_route_remove(match, ospf6->external_table);
XFREE(MTYPE_OSPF6_EXTERNAL_INFO, info);
- /* Router-Bit (ASBR Flag) may have to be updated */
- for (ALL_LIST_ELEMENTS(ospf6->area_list, lnode, lnnode, oa))
- OSPF6_ROUTER_LSA_SCHEDULE(oa);
+ ospf6_asbr_status_update(ospf6, ospf6->redistribute);
}
DEFUN (ospf6_redistribute,
@@ -1533,6 +1574,140 @@ static void ospf6_redistribute_show_config(struct vty *vty, struct ospf6 *ospf6,
vty_out(vty, "Total %d routes\n", total);
}
+static void ospf6_redistribute_default_set(struct ospf6 *ospf6, int originate)
+{
+ struct prefix_ipv6 p = {};
+ struct in6_addr nexthop = {};
+ int cur_originate = ospf6->default_originate;
+
+ p.family = AF_INET6;
+ p.prefixlen = 0;
+
+ ospf6->default_originate = originate;
+
+ switch (cur_originate) {
+ case DEFAULT_ORIGINATE_NONE:
+ break;
+ case DEFAULT_ORIGINATE_ZEBRA:
+ zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
+ zclient, AFI_IP6, ospf6->vrf_id);
+ ospf6_asbr_redistribute_remove(DEFAULT_ROUTE, 0,
+ (struct prefix *)&p, ospf6);
+
+ break;
+ case DEFAULT_ORIGINATE_ALWAYS:
+ ospf6_asbr_redistribute_remove(DEFAULT_ROUTE, 0,
+ (struct prefix *)&p, ospf6);
+ break;
+ }
+
+ switch (originate) {
+ case DEFAULT_ORIGINATE_NONE:
+ break;
+ case DEFAULT_ORIGINATE_ZEBRA:
+ zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
+ zclient, AFI_IP6, ospf6->vrf_id);
+
+ break;
+ case DEFAULT_ORIGINATE_ALWAYS:
+ ospf6_asbr_redistribute_add(DEFAULT_ROUTE, 0,
+ (struct prefix *)&p, 0, &nexthop, 0,
+ ospf6);
+ break;
+ }
+}
+
+/* Default Route originate. */
+DEFPY (ospf6_default_route_originate,
+ ospf6_default_route_originate_cmd,
+ "default-information originate [{always$always|metric (0-16777214)$mval|metric-type (1-2)$mtype|route-map WORD$rtmap}]",
+ "Control distribution of default route\n"
+ "Distribute a default route\n"
+ "Always advertise default route\n"
+ "OSPFv3 default metric\n"
+ "OSPFv3 metric\n"
+ "OSPFv3 metric type for default routes\n"
+ "Set OSPFv3 External Type 1/2 metrics\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ int default_originate = DEFAULT_ORIGINATE_ZEBRA;
+ struct ospf6_redist *red;
+ bool sameRtmap = false;
+
+ VTY_DECLVAR_CONTEXT(ospf6, ospf6);
+
+ int cur_originate = ospf6->default_originate;
+
+ OSPF6_CMD_CHECK_RUNNING(ospf6);
+
+ red = ospf6_redist_add(ospf6, DEFAULT_ROUTE, 0);
+
+ if (always != NULL)
+ default_originate = DEFAULT_ORIGINATE_ALWAYS;
+
+ if (mval_str == NULL)
+ mval = -1;
+
+ if (mtype_str == NULL)
+ mtype = -1;
+
+ /* To check ,if user is providing same route map */
+ if ((rtmap == ROUTEMAP_NAME(red))
+ || (rtmap && ROUTEMAP_NAME(red)
+ && (strcmp(rtmap, ROUTEMAP_NAME(red)) == 0)))
+ sameRtmap = true;
+
+ /* Don't allow if the same lsa is aleardy originated. */
+ if ((sameRtmap) && (red->dmetric.type == mtype)
+ && (red->dmetric.value == mval)
+ && (cur_originate == default_originate))
+ return CMD_SUCCESS;
+
+ /* Updating Metric details */
+ red->dmetric.type = mtype;
+ red->dmetric.value = mval;
+
+ /* updating route map details */
+ if (rtmap)
+ ospf6_asbr_routemap_set(red, rtmap);
+ else
+ ospf6_asbr_routemap_unset(red);
+
+ ospf6_redistribute_default_set(ospf6, default_originate);
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_ospf6_default_information_originate,
+ no_ospf6_default_information_originate_cmd,
+ "no default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map WORD}]",
+ NO_STR
+ "Control distribution of default information\n"
+ "Distribute a default route\n"
+ "Always advertise default route\n"
+ "OSPFv3 default metric\n"
+ "OSPFv3 metric\n"
+ "OSPFv3 metric type for default routes\n"
+ "Set OSPFv3 External Type 1/2 metrics\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ struct ospf6_redist *red;
+
+ VTY_DECLVAR_CONTEXT(ospf6, ospf6);
+
+ OSPF6_CMD_CHECK_RUNNING(ospf6);
+
+ red = ospf6_redist_lookup(ospf6, DEFAULT_ROUTE, 0);
+ if (!red)
+ return CMD_SUCCESS;
+
+ ospf6_asbr_routemap_unset(red);
+ ospf6_redist_del(ospf6, red, DEFAULT_ROUTE);
+
+ ospf6_redistribute_default_set(ospf6, DEFAULT_ORIGINATE_NONE);
+ return CMD_SUCCESS;
+}
/* Routemap Functions */
static enum route_map_cmd_result_t
@@ -1750,99 +1925,83 @@ ospf6_routemap_rule_set_tag(void *rule, const struct prefix *p, void *object)
return RMAP_OKAY;
}
-static const struct route_map_rule_cmd
- ospf6_routemap_rule_set_tag_cmd = {
+static const struct route_map_rule_cmd ospf6_routemap_rule_set_tag_cmd = {
"tag",
ospf6_routemap_rule_set_tag,
route_map_rule_tag_compile,
route_map_rule_tag_free,
};
-static int route_map_command_status(struct vty *vty, enum rmap_compile_rets ret)
-{
- switch (ret) {
- case RMAP_RULE_MISSING:
- vty_out(vty, "OSPF6 Can't find rule.\n");
- return CMD_WARNING_CONFIG_FAILED;
- case RMAP_COMPILE_ERROR:
- vty_out(vty, "OSPF6 Argument is malformed.\n");
- return CMD_WARNING_CONFIG_FAILED;
- case RMAP_COMPILE_SUCCESS:
- break;
- }
-
- return CMD_SUCCESS;
-}
-
/* add "set metric-type" */
-DEFUN (ospf6_routemap_set_metric_type,
- ospf6_routemap_set_metric_type_cmd,
- "set metric-type <type-1|type-2>",
- "Set value\n"
- "Type of metric\n"
- "OSPF6 external type 1 metric\n"
- "OSPF6 external type 2 metric\n")
+DEFUN_YANG (ospf6_routemap_set_metric_type, ospf6_routemap_set_metric_type_cmd,
+ "set metric-type <type-1|type-2>",
+ "Set value\n"
+ "Type of metric\n"
+ "OSPF6 external type 1 metric\n"
+ "OSPF6 external type 2 metric\n")
{
- VTY_DECLVAR_CONTEXT(route_map_index, route_map_index);
- int idx_external = 2;
- enum rmap_compile_rets ret = route_map_add_set(route_map_index,
- "metric-type",
- argv[idx_external]->arg);
+ char *ext = argv[2]->text;
- return route_map_command_status(vty, ret);
+ const char *xpath =
+ "./set-action[action='frr-ospf-route-map:metric-type']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-set-action/frr-ospf-route-map:metric-type", xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ext);
+ return nb_cli_apply_changes(vty, NULL);
}
/* delete "set metric-type" */
-DEFUN (ospf6_routemap_no_set_metric_type,
- ospf6_routemap_no_set_metric_type_cmd,
- "no set metric-type [<type-1|type-2>]",
- NO_STR
- "Set value\n"
- "Type of metric\n"
- "OSPF6 external type 1 metric\n"
- "OSPF6 external type 2 metric\n")
+DEFUN_YANG (ospf6_routemap_no_set_metric_type, ospf6_routemap_no_set_metric_type_cmd,
+ "no set metric-type [<type-1|type-2>]",
+ NO_STR
+ "Set value\n"
+ "Type of metric\n"
+ "OSPF6 external type 1 metric\n"
+ "OSPF6 external type 2 metric\n")
{
- VTY_DECLVAR_CONTEXT(route_map_index, route_map_index);
- char *ext = (argc == 4) ? argv[3]->text : NULL;
- enum rmap_compile_rets ret = route_map_delete_set(route_map_index,
- "metric-type", ext);
+ const char *xpath =
+ "./set-action[action='frr-ospf-route-map:metric-type']";
- return route_map_command_status(vty, ret);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
}
/* add "set forwarding-address" */
-DEFUN (ospf6_routemap_set_forwarding,
- ospf6_routemap_set_forwarding_cmd,
- "set forwarding-address X:X::X:X",
- "Set value\n"
- "Forwarding Address\n"
- "IPv6 Address\n")
-{
- VTY_DECLVAR_CONTEXT(route_map_index, route_map_index);
+DEFUN_YANG (ospf6_routemap_set_forwarding, ospf6_routemap_set_forwarding_cmd,
+ "set forwarding-address X:X::X:X",
+ "Set value\n"
+ "Forwarding Address\n"
+ "IPv6 Address\n")
+{
int idx_ipv6 = 2;
- enum rmap_compile_rets ret = route_map_add_set(route_map_index,
- "forwarding-address",
- argv[idx_ipv6]->arg);
-
- return route_map_command_status(vty, ret);
+ const char *xpath =
+ "./set-action[action='frr-ospf6-route-map:forwarding-address']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-set-action/frr-ospf6-route-map:ipv6-address", xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
+ argv[idx_ipv6]->arg);
+ return nb_cli_apply_changes(vty, NULL);
}
/* delete "set forwarding-address" */
-DEFUN (ospf6_routemap_no_set_forwarding,
- ospf6_routemap_no_set_forwarding_cmd,
- "no set forwarding-address X:X::X:X",
- NO_STR
- "Set value\n"
- "Forwarding Address\n"
- "IPv6 Address\n")
+DEFUN_YANG (ospf6_routemap_no_set_forwarding, ospf6_routemap_no_set_forwarding_cmd,
+ "no set forwarding-address [X:X::X:X]",
+ NO_STR
+ "Set value\n"
+ "Forwarding Address\n"
+ "IPv6 Address\n")
{
- VTY_DECLVAR_CONTEXT(route_map_index, route_map_index);
- int idx_ipv6 = 3;
- enum rmap_compile_rets ret = route_map_delete_set(route_map_index,
- "forwarding-address",
- argv[idx_ipv6]->arg);
+ const char *xpath =
+ "./set-action[action='frr-ospf6-route-map:forwarding-address']";
- return route_map_command_status(vty, ret);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
}
static void ospf6_routemap_init(void)
@@ -2115,6 +2274,9 @@ void ospf6_asbr_init(void)
install_element(VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
+ install_element(OSPF6_NODE, &ospf6_default_route_originate_cmd);
+ install_element(OSPF6_NODE,
+ &no_ospf6_default_information_originate_cmd);
install_element(OSPF6_NODE, &ospf6_redistribute_cmd);
install_element(OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
install_element(OSPF6_NODE, &no_ospf6_redistribute_cmd);
@@ -2176,6 +2338,39 @@ int config_write_ospf6_debug_asbr(struct vty *vty)
return 0;
}
+int ospf6_distribute_config_write(struct vty *vty, struct ospf6 *ospf6)
+{
+ struct ospf6_redist *red;
+
+ if (ospf6) {
+ /* default-route print. */
+ if (ospf6->default_originate != DEFAULT_ORIGINATE_NONE) {
+ vty_out(vty, " default-information originate");
+ if (ospf6->default_originate
+ == DEFAULT_ORIGINATE_ALWAYS)
+ vty_out(vty, " always");
+
+ red = ospf6_redist_lookup(ospf6, DEFAULT_ROUTE, 0);
+ if (red) {
+ if (red->dmetric.value >= 0)
+ vty_out(vty, " metric %d",
+ red->dmetric.value);
+
+ if (red->dmetric.type >= 0)
+ vty_out(vty, " metric-type %d",
+ red->dmetric.type);
+
+ if (ROUTEMAP_NAME(red))
+ vty_out(vty, " route-map %s",
+ ROUTEMAP_NAME(red));
+ }
+
+ vty_out(vty, "\n");
+ }
+ }
+ return 0;
+}
+
void install_element_ospf6_debug_asbr(void)
{
install_element(ENABLE_NODE, &debug_ospf6_asbr_cmd);