mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-02 13:23:44 +00:00
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:
parent
e95c4d17a7
commit
baff583e8b
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user