summaryrefslogtreecommitdiffstats
path: root/ospf6d/ospf6_zebra.c
diff options
context:
space:
mode:
authorMaitane Zotes <maz@open.ch>2014-03-05 09:13:43 +0100
committerDonald Sharp <sharpd@cumulusnetworks.com>2016-10-20 04:28:45 +0200
commitbaff583e8bb5f703ab07aab55fea9a7ddf42a468 (patch)
treecd53c2b4c2547a59994bc283a1d6ebf0f12d68e9 /ospf6d/ospf6_zebra.c
parent*: Fix duplicate commands from view/enable node consolidation (diff)
downloadfrr-baff583e8bb5f703ab07aab55fea9a7ddf42a468.tar.xz
frr-baff583e8bb5f703ab07aab55fea9a7ddf42a468.zip
ospf6d: implement admin distance
Until today the admin distance cannot be configured for any IPv6 routing protocol. This patch implements it for ospf6. Signed-off-by: Maitane Zotes <maz@open.ch> Signed-off-by: Roman Hoog Antink <rha@open.ch>
Diffstat (limited to 'ospf6d/ospf6_zebra.c')
-rw-r--r--ospf6d/ospf6_zebra.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 4d658ed1b..3e4042d65 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -40,6 +40,8 @@
#include "ospf6_zebra.h"
#include "ospf6d.h"
+DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_DISTANCE, "OSPF6 distance")
+
unsigned char conf_debug_ospf6_zebra = 0;
/* information about zebra. */
@@ -480,6 +482,10 @@ ospf6_zebra_route_update (int type, struct ospf6_route *request)
}
dest = (struct prefix_ipv6 *) &request->prefix;
+
+ SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
+ api.distance = ospf6_distance_apply (dest, request);
+
if (type == REM)
ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, &api);
else
@@ -664,6 +670,150 @@ DEFUN (no_redistribute_ospf6,
return CMD_SUCCESS;
}
+static struct ospf6_distance *
+ospf6_distance_new (void)
+{
+ return XCALLOC (MTYPE_OSPF6_DISTANCE, sizeof (struct ospf6_distance));
+}
+
+static void
+ospf6_distance_free (struct ospf6_distance *odistance)
+{
+ XFREE (MTYPE_OSPF6_DISTANCE, odistance);
+}
+
+int
+ospf6_distance_set (struct vty *vty, struct ospf6 *o,
+ const char *distance_str,
+ const char *ip_str,
+ const char *access_list_str)
+{
+ int ret;
+ struct prefix_ipv6 p;
+ u_char distance;
+ struct route_node *rn;
+ struct ospf6_distance *odistance;
+
+ ret = str2prefix_ipv6 (ip_str, &p);
+ if (ret == 0)
+ {
+ vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ distance = atoi (distance_str);
+
+ /* Get OSPF6 distance node. */
+ rn = route_node_get (o->distance_table, (struct prefix *) &p);
+ if (rn->info)
+ {
+ odistance = rn->info;
+ route_unlock_node (rn);
+ }
+ else
+ {
+ odistance = ospf6_distance_new ();
+ rn->info = odistance;
+ }
+
+ /* Set distance value. */
+ odistance->distance = distance;
+
+ /* Reset access-list configuration. */
+ if (odistance->access_list)
+ {
+ free (odistance->access_list);
+ odistance->access_list = NULL;
+ }
+ if (access_list_str)
+ odistance->access_list = strdup (access_list_str);
+
+ return CMD_SUCCESS;
+}
+
+int
+ospf6_distance_unset (struct vty *vty, struct ospf6 *o,
+ const char *distance_str,
+ const char *ip_str,
+ const char *access_list_str)
+{
+ int ret;
+ struct prefix_ipv6 p;
+ struct route_node *rn;
+ struct ospf6_distance *odistance;
+
+ ret = str2prefix_ipv6 (ip_str, &p);
+ if (ret == 0)
+ {
+ vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ rn = route_node_lookup (o->distance_table, (struct prefix *) &p);
+ if (!rn)
+ {
+ vty_out (vty, "Cant't find specified prefix%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ odistance = rn->info;
+
+ if (odistance->access_list)
+ free (odistance->access_list);
+ ospf6_distance_free (odistance);
+
+ rn->info = NULL;
+ route_unlock_node (rn);
+ route_unlock_node (rn);
+
+ return CMD_SUCCESS;
+}
+
+void
+ospf6_distance_reset (struct ospf6 *o)
+{
+ struct route_node *rn;
+ struct ospf6_distance *odistance;
+
+ for (rn = route_top (o->distance_table); rn; rn = route_next (rn))
+ if ((odistance = rn->info) != NULL)
+ {
+ if (odistance->access_list)
+ free (odistance->access_list);
+ ospf6_distance_free (odistance);
+ rn->info = NULL;
+ route_unlock_node (rn);
+ }
+}
+
+u_char
+ospf6_distance_apply (struct prefix_ipv6 *p, struct ospf6_route *or)
+{
+ struct ospf6 *o;
+
+ o = ospf6;
+ if (o == NULL)
+ return 0;
+
+ if (o->distance_intra)
+ if (or->path.type == OSPF6_PATH_TYPE_INTRA)
+ return o->distance_intra;
+
+ if (o->distance_inter)
+ if (or->path.type == OSPF6_PATH_TYPE_INTER)
+ return o->distance_inter;
+
+ if (o->distance_external)
+ if(or->path.type == OSPF6_PATH_TYPE_EXTERNAL1
+ || or->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
+ return o->distance_external;
+
+ if (o->distance_all)
+ return o->distance_all;
+
+ return 0;
+}
+
static void
ospf6_zebra_connected (struct zclient *zclient)
{