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>
This commit is contained in:
Maitane Zotes 2014-03-05 09:13:43 +01:00 committed by Donald Sharp
parent e95c4d17a7
commit baff583e8b
4 changed files with 362 additions and 0 deletions

View File

@ -155,6 +155,8 @@ ospf6_create (void)
o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
o->distance_table = route_table_init ();
/* Enable "log-adjacency-changes" */
SET_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
@ -184,6 +186,9 @@ ospf6_delete (struct ospf6 *o)
ospf6_route_table_delete (o->external_table);
route_table_finish (o->external_id_table);
ospf6_distance_reset (o);
route_table_finish (o->distance_table);
XFREE (MTYPE_OSPF6_TOP, o);
}
@ -460,6 +465,138 @@ ALIAS (no_ospf6_timers_lsa,
"Minimum delay in receiving new version of a LSA\n"
"Delay in milliseconds\n")
DEFUN (ospf6_distance,
ospf6_distance_cmd,
"distance <1-255>",
"Administrative distance\n"
"OSPF6 Administrative distance\n")
{
struct ospf6 *o = vty->index;
o->distance_all = atoi (argv[0]);
return CMD_SUCCESS;
}
DEFUN (no_ospf6_distance,
no_ospf6_distance_cmd,
"no distance <1-255>",
NO_STR
"Administrative distance\n"
"OSPF6 Administrative distance\n")
{
struct ospf6 *o = vty->index;
o->distance_all = 0;
return CMD_SUCCESS;
}
DEFUN (ospf6_distance_ospf6,
ospf6_distance_ospf6_cmd,
"distance ospf6 {intra-area <1-255>|inter-area <1-255>|external <1-255>}",
"Administrative distance\n"
"OSPF6 distance\n"
"Intra-area routes\n"
"Distance for intra-area routes\n"
"Inter-area routes\n"
"Distance for inter-area routes\n"
"External routes\n"
"Distance for external routes\n")
{
struct ospf6 *o = vty->index;
if (argc < 3) /* should not happen */
return CMD_WARNING;
if (!argv[0] && !argv[1] && !argv[2])
{
vty_out(vty, "%% Command incomplete. (Arguments required)%s",
VTY_NEWLINE);
return CMD_WARNING;
}
if (argv[0] != NULL)
o->distance_intra = atoi (argv[0]);
if (argv[1] != NULL)
o->distance_inter = atoi (argv[1]);
if (argv[2] != NULL)
o->distance_external = atoi (argv[2]);
return CMD_SUCCESS;
}
DEFUN (no_ospf6_distance_ospf6,
no_ospf6_distance_ospf6_cmd,
"no distance ospf6 {intra-area <1-255>|inter-area <1-255>|external <1-255>}",
NO_STR
"Administrative distance\n"
"OSPF6 distance\n"
"Intra-area routes\n"
"Distance for intra-area routes\n"
"Inter-area routes\n"
"Distance for inter-area routes\n"
"External routes\n"
"Distance for external routes\n")
{
struct ospf6 *o = vty->index;
if (argc < 3) /* should not happen */
return CMD_WARNING;
if (argv[0] != NULL)
o->distance_intra = 0;
if (argv[1] != NULL)
o->distance_inter = 0;
if (argv[2] != NULL)
o->distance_external = 0;
if (argv[0] || argv[1] || argv[2])
return CMD_SUCCESS;
/* If no arguments are given, clear all distance information */
o->distance_intra = 0;
o->distance_inter = 0;
o->distance_external = 0;
return CMD_SUCCESS;
}
DEFUN (ospf6_distance_source,
ospf6_distance_source_cmd,
"distance <1-255> X:X::X:X/M [WORD]",
"Administrative distance\n"
"Distance value\n"
"IP source prefix\n"
"Access list name\n")
{
struct ospf6 *o = vty->index;
ospf6_distance_set (vty, o, argv[0], argv[1], argc == 3 ? argv[2] : NULL);
return CMD_SUCCESS;
}
DEFUN (no_ospf6_distance_source,
no_ospf6_distance_source_cmd,
"no distance <1-255> X:X::X:X/M [WORD]",
NO_STR
"Administrative distance\n"
"Distance value\n"
"IP source prefix\n"
"Access list name\n")
{
struct ospf6 *o = vty->index;
ospf6_distance_unset (vty, o, argv[0], argv[1], argc == 3 ? argv[2] : NULL);
return CMD_SUCCESS;
}
DEFUN (ospf6_interface_area,
ospf6_interface_area_cmd,
"interface IFNAME area A.B.C.D",
@ -934,6 +1071,44 @@ ospf6_stub_router_config_write (struct vty *vty)
return;
}
static int
ospf6_distance_config_write (struct vty *vty)
{
struct route_node *rn;
struct ospf6_distance *odistance;
if (ospf6->distance_all)
vty_out (vty, " distance %u%s", ospf6->distance_all, VTY_NEWLINE);
if (ospf6->distance_intra
|| ospf6->distance_inter
|| ospf6->distance_external)
{
vty_out (vty, " distance ospf6");
if (ospf6->distance_intra)
vty_out (vty, " intra-area %u", ospf6->distance_intra);
if (ospf6->distance_inter)
vty_out (vty, " inter-area %u", ospf6->distance_inter);
if (ospf6->distance_external)
vty_out (vty, " external %u", ospf6->distance_external);
vty_out (vty, "%s", VTY_NEWLINE);
}
for (rn = route_top (ospf6->distance_table); rn; rn = route_next (rn))
if ((odistance = rn->info) != NULL)
{
char buf[PREFIX_STRLEN];
vty_out (vty, " distance %u %s %s%s", odistance->distance,
prefix2str (&rn->p, buf, sizeof (buf)),
odistance->access_list ? odistance->access_list : "",
VTY_NEWLINE);
}
return 0;
}
/* OSPF configuration write function. */
static int
config_write_ospf6 (struct vty *vty)
@ -976,6 +1151,7 @@ config_write_ospf6 (struct vty *vty)
ospf6_redistribute_config_write (vty);
ospf6_area_config_write (vty);
ospf6_spf_config_write (vty);
ospf6_distance_config_write (vty);
for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, j, oa))
{
@ -1037,6 +1213,15 @@ ospf6_top_init (void)
install_element (OSPF6_NODE, &ospf6_stub_router_shutdown_cmd);
install_element (OSPF6_NODE, &no_ospf6_stub_router_shutdown_cmd);
*/
install_element (OSPF6_NODE, &ospf6_distance_cmd);
install_element (OSPF6_NODE, &no_ospf6_distance_cmd);
install_element (OSPF6_NODE, &ospf6_distance_ospf6_cmd);
install_element (OSPF6_NODE, &no_ospf6_distance_ospf6_cmd);
#if 0
install_element (OSPF6_NODE, &ospf6_distance_source_cmd);
install_element (OSPF6_NODE, &no_ospf6_distance_source_cmd);
#endif
}

View File

@ -85,6 +85,14 @@ struct ospf6
struct thread *maxage_remover;
u_int32_t ref_bandwidth;
/* Distance parameters */
u_char distance_all;
u_char distance_intra;
u_char distance_inter;
u_char distance_external;
struct route_table *distance_table;
};
#define OSPF6_DISABLED 0x01

View File

@ -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)
{

View File

@ -35,6 +35,16 @@ extern unsigned char conf_debug_ospf6_zebra;
#define IS_OSPF6_DEBUG_ZEBRA(e) \
(conf_debug_ospf6_zebra & OSPF6_DEBUG_ZEBRA_ ## e)
/* OSPF6 distance */
struct ospf6_distance
{
/* Distance value for the IP source prefix */
u_char distance;
/* Name of the access-list to be matched */
char *access_list;
};
extern struct zclient *zclient;
extern void ospf6_zebra_route_update_add (struct ospf6_route *request);
@ -48,6 +58,15 @@ extern void ospf6_zebra_init (struct thread_master *);
extern void ospf6_zebra_add_discard (struct ospf6_route *request);
extern void ospf6_zebra_delete_discard (struct ospf6_route *request);
struct ospf6;
extern void ospf6_distance_reset (struct ospf6 *);
extern u_char ospf6_distance_apply (struct prefix_ipv6 *, struct ospf6_route *);
extern int ospf6_distance_set (struct vty *, struct ospf6 *, const char *,
const char *, const char *);
extern int ospf6_distance_unset (struct vty *, struct ospf6 *, const char *,
const char *, const char *);
extern int config_write_ospf6_debug_zebra (struct vty *vty);
extern void install_element_ospf6_debug_zebra (void);