mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 16:20:08 +00:00
ospf6d: ASBR Summarisation feature implementation
Feature Implementation. ======================== This feature will help in advertising the External LSAs with aggregation. The commands allow us to tune the advertisement with different parameters as mentioned in the CLI List below. It can also help in case we do not want to advertise any prefix with the no-advertise option. New CLIs added: =============== summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)}] no summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)}] summary-address X:X::X:X/M$prefix no-advertise no summary-address X:X::X:X/M$prefix no-advertise aggregation timer (5-1800) no aggregation timer (5-1800) show ipv6 ospf6 summary-address [detail$detail] [json] debug ospf6 lsa aggregation CAT RUN: ======== QE to add test scripts Signed-Off-by: Mobashshera Rasool <mrassol@vmware.com>
This commit is contained in:
parent
2e69d1e4f3
commit
4dc4388691
1139
ospf6d/ospf6_asbr.c
1139
ospf6d/ospf6_asbr.c
File diff suppressed because it is too large
Load Diff
@ -46,6 +46,52 @@ struct ospf6_external_info {
|
||||
route_tag_t tag;
|
||||
|
||||
ifindex_t ifindex;
|
||||
|
||||
};
|
||||
|
||||
/* OSPF6 ASBR Summarisation */
|
||||
typedef enum {
|
||||
OSPF6_ROUTE_AGGR_NONE = 0,
|
||||
OSPF6_ROUTE_AGGR_ADD,
|
||||
OSPF6_ROUTE_AGGR_DEL,
|
||||
OSPF6_ROUTE_AGGR_MODIFY
|
||||
}ospf6_aggr_action_t;
|
||||
|
||||
#define OSPF6_EXTERNAL_AGGRT_NO_ADVERTISE 0x1
|
||||
#define OSPF6_EXTERNAL_AGGRT_ORIGINATED 0x2
|
||||
|
||||
#define OSPF6_EXTERNAL_RT_COUNT(aggr) \
|
||||
(((struct ospf6_external_aggr_rt *)aggr)->match_extnl_hash->count)
|
||||
|
||||
struct ospf6_external_aggr_rt {
|
||||
/* range address and masklen */
|
||||
struct prefix p;
|
||||
|
||||
/* use bits for OSPF6_EXTERNAL_AGGRT_NO_ADVERTISE and
|
||||
* OSPF6_EXTERNAL_AGGRT_ORIGINATED
|
||||
*/
|
||||
uint16_t aggrflags;
|
||||
|
||||
/* To store external metric-type */
|
||||
uint8_t mtype;
|
||||
|
||||
/* Route tag for summary address */
|
||||
route_tag_t tag;
|
||||
|
||||
/* To store aggregated metric config */
|
||||
int metric;
|
||||
|
||||
/* To Store the LS ID when LSA is originated */
|
||||
uint32_t id;
|
||||
|
||||
/* How many prefixes are using this range */
|
||||
uint32_t refcount;
|
||||
|
||||
/* Action to be done after delay timer expiry */
|
||||
int action;
|
||||
|
||||
/* Hash table of matching external routes */
|
||||
struct hash *match_extnl_hash;
|
||||
};
|
||||
|
||||
/* AS-External-LSA */
|
||||
@ -110,8 +156,28 @@ extern void ospf6_asbr_distribute_list_update(struct ospf6 *ospf6,
|
||||
struct ospf6_redist *ospf6_redist_lookup(struct ospf6 *ospf6, int type,
|
||||
unsigned short instance);
|
||||
extern void ospf6_asbr_routemap_update(const char *mapname);
|
||||
extern void ospf6_as_external_lsa_originate(struct ospf6_route *route,
|
||||
extern struct ospf6_lsa *ospf6_as_external_lsa_originate(struct ospf6_route *route,
|
||||
struct ospf6 *ospf6);
|
||||
extern void ospf6_asbr_status_update(struct ospf6 *ospf6, int status);
|
||||
|
||||
int ospf6_asbr_external_rt_advertise(struct ospf6 *ospf6,
|
||||
struct prefix *p);
|
||||
int ospf6_external_aggr_delay_timer_set(struct ospf6 *ospf6,
|
||||
unsigned int interval);
|
||||
int ospf6_asbr_external_rt_no_advertise(struct ospf6 *ospf6,
|
||||
struct prefix *p);
|
||||
|
||||
struct ospf6_external_aggr_rt *
|
||||
ospf6_external_aggr_config_lookup(struct ospf6 *ospf6, struct prefix *p);
|
||||
|
||||
int ospf6_external_aggr_config_set(struct ospf6 *ospf6, struct prefix *p,
|
||||
route_tag_t tag, int metric, int mtype);
|
||||
|
||||
int ospf6_external_aggr_config_unset(struct ospf6 *ospf6,
|
||||
struct prefix *p);
|
||||
void ospf6_handle_external_lsa_origination(struct ospf6 *ospf6,
|
||||
struct ospf6_route *rt,
|
||||
struct prefix *p);
|
||||
void ospf6_external_aggregator_free(struct ospf6_external_aggr_rt *aggr);
|
||||
void ospf6_unset_all_aggr_flag(struct ospf6 *ospf6);
|
||||
#endif /* OSPF6_ASBR_H */
|
||||
|
@ -106,7 +106,7 @@ void ospf6_lsa_originate(struct ospf6_lsa *lsa)
|
||||
lsdb_self = ospf6_get_scoped_lsdb_self(lsa);
|
||||
ospf6_lsdb_add(ospf6_lsa_copy(lsa), lsdb_self);
|
||||
|
||||
lsa->refresh = NULL;
|
||||
THREAD_OFF(lsa->refresh);
|
||||
thread_add_timer(master, ospf6_lsa_refresh, lsa, OSPF_LS_REFRESH_TIME,
|
||||
&lsa->refresh);
|
||||
|
||||
@ -139,6 +139,31 @@ void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa,
|
||||
ospf6_lsa_originate(lsa);
|
||||
}
|
||||
|
||||
void ospf6_remove_id_from_external_id_table(struct ospf6 *ospf6,
|
||||
uint32_t id)
|
||||
{
|
||||
struct prefix prefix_id;
|
||||
struct route_node *node;
|
||||
|
||||
/* remove binding in external_id_table */
|
||||
prefix_id.family = AF_INET;
|
||||
prefix_id.prefixlen = 32;
|
||||
prefix_id.u.prefix4.s_addr = id;
|
||||
node = route_node_lookup(ospf6->external_id_table, &prefix_id);
|
||||
assert(node);
|
||||
node->info = NULL;
|
||||
route_unlock_node(node); /* to free the lookup lock */
|
||||
route_unlock_node(node); /* to free the original lock */
|
||||
|
||||
}
|
||||
|
||||
void ospf6_external_lsa_purge(struct ospf6 *ospf6, struct ospf6_lsa *lsa)
|
||||
{
|
||||
ospf6_lsa_purge(lsa);
|
||||
|
||||
ospf6_remove_id_from_external_id_table(ospf6, lsa->header->id);
|
||||
}
|
||||
|
||||
void ospf6_lsa_purge(struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_lsa *self;
|
||||
|
@ -39,6 +39,9 @@ extern void ospf6_lsa_originate_area(struct ospf6_lsa *lsa,
|
||||
struct ospf6_area *oa);
|
||||
extern void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa,
|
||||
struct ospf6_interface *oi);
|
||||
void ospf6_remove_id_from_external_id_table(struct ospf6 *ospf6,
|
||||
uint32_t id);
|
||||
void ospf6_external_lsa_purge(struct ospf6 *ospf6, struct ospf6_lsa *lsa);
|
||||
extern void ospf6_lsa_purge(struct ospf6_lsa *lsa);
|
||||
|
||||
extern void ospf6_lsa_purge_multi_ls_id(struct ospf6_area *oa,
|
||||
|
@ -45,6 +45,10 @@
|
||||
#include "ospf6_flood.h"
|
||||
#include "ospf6d.h"
|
||||
|
||||
#ifndef VTYSH_EXTRACT_PL
|
||||
#include "ospf6d/ospf6_lsa_clippy.c"
|
||||
#endif
|
||||
|
||||
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA");
|
||||
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_HEADER, "OSPF6 LSA header");
|
||||
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_SUMMARY, "OSPF6 LSA summary");
|
||||
@ -822,6 +826,8 @@ int ospf6_lsa_expire(struct thread *thread)
|
||||
if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
|
||||
return 0; /* dbexchange will do something ... */
|
||||
ospf6 = ospf6_get_by_lsdb(lsa);
|
||||
assert(ospf6);
|
||||
|
||||
/* reinstall lsa */
|
||||
ospf6_install_lsa(lsa);
|
||||
|
||||
@ -994,6 +1000,30 @@ static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler *h)
|
||||
return buf;
|
||||
}
|
||||
|
||||
DEFPY (debug_ospf6_lsa_aggregation,
|
||||
debug_ospf6_lsa_aggregation_cmd,
|
||||
"[no] debug ospf6 lsa aggregation",
|
||||
NO_STR
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Debug Link State Advertisements (LSAs)\n"
|
||||
"External LSA Aggregation\n")
|
||||
{
|
||||
|
||||
struct ospf6_lsa_handler *handler;
|
||||
|
||||
handler = ospf6_get_lsa_handler(OSPF6_LSTYPE_AS_EXTERNAL);
|
||||
if (handler == NULL)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
if (no)
|
||||
UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR);
|
||||
else
|
||||
SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (debug_ospf6_lsa_type,
|
||||
debug_ospf6_lsa_hex_cmd,
|
||||
"debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
|
||||
@ -1105,6 +1135,9 @@ void install_element_ospf6_debug_lsa(void)
|
||||
install_element(ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
|
||||
install_element(CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
|
||||
|
||||
install_element(ENABLE_NODE, &debug_ospf6_lsa_aggregation_cmd);
|
||||
install_element(CONFIG_NODE, &debug_ospf6_lsa_aggregation_cmd);
|
||||
}
|
||||
|
||||
int config_write_ospf6_debug_lsa(struct vty *vty)
|
||||
@ -1128,6 +1161,8 @@ int config_write_ospf6_debug_lsa(struct vty *vty)
|
||||
if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD))
|
||||
vty_out(vty, "debug ospf6 lsa %s flooding\n",
|
||||
ospf6_lsa_handler_name(handler));
|
||||
if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR))
|
||||
vty_out(vty, "debug ospf6 lsa aggregation\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#define OSPF6_LSA_DEBUG_ORIGINATE 0x02
|
||||
#define OSPF6_LSA_DEBUG_EXAMIN 0x04
|
||||
#define OSPF6_LSA_DEBUG_FLOOD 0x08
|
||||
#define OSPF6_LSA_DEBUG_AGGR 0x10
|
||||
|
||||
/* OSPF LSA Default metric values */
|
||||
#define DEFAULT_DEFAULT_METRIC 20
|
||||
@ -51,6 +52,8 @@
|
||||
(ospf6_lstype_debug(type) & OSPF6_LSA_DEBUG_EXAMIN)
|
||||
#define IS_OSPF6_DEBUG_FLOOD_TYPE(type) \
|
||||
(ospf6_lstype_debug(type) & OSPF6_LSA_DEBUG_FLOOD)
|
||||
#define IS_OSPF6_DEBUG_AGGR \
|
||||
(ospf6_lstype_debug(OSPF6_LSTYPE_AS_EXTERNAL) & OSPF6_LSA_DEBUG_AGGR) \
|
||||
|
||||
/* LSA definition */
|
||||
|
||||
@ -263,4 +266,5 @@ extern void install_element_ospf6_debug_lsa(void);
|
||||
extern void ospf6_lsa_age_set(struct ospf6_lsa *lsa);
|
||||
extern void ospf6_flush_self_originated_lsas_now(struct ospf6 *ospf6);
|
||||
extern struct ospf6 *ospf6_get_by_lsdb(struct ospf6_lsa *lsa);
|
||||
struct ospf6_lsa *ospf6_find_external_lsa(struct ospf6 *ospf6, struct prefix *p);
|
||||
#endif /* OSPF6_LSA_H */
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "ospf6_proto.h"
|
||||
#include "ospf6_lsa.h"
|
||||
#include "ospf6_lsdb.h"
|
||||
#include "ospf6_asbr.h"
|
||||
#include "ospf6_route.h"
|
||||
#include "ospf6d.h"
|
||||
#include "bitfield.h"
|
||||
@ -194,6 +195,28 @@ struct ospf6_lsa *ospf6_lsdb_lookup(uint16_t type, uint32_t id,
|
||||
return (struct ospf6_lsa *)node->info;
|
||||
}
|
||||
|
||||
struct ospf6_lsa *ospf6_find_external_lsa(struct ospf6 *ospf6, struct prefix *p)
|
||||
{
|
||||
struct ospf6_route *match;
|
||||
struct ospf6_lsa *lsa;
|
||||
struct ospf6_external_info *info;
|
||||
|
||||
match = ospf6_route_lookup(p, ospf6->external_table);
|
||||
if (match == NULL) {
|
||||
if (IS_OSPF6_DEBUG_ASBR)
|
||||
zlog_debug("No such route %pFX to withdraw", p);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info = (struct ospf6_external_info *)(match->route_option);
|
||||
assert(info);
|
||||
|
||||
lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
|
||||
htonl(info->id), ospf6->router_id, ospf6->lsdb);
|
||||
return lsa;
|
||||
}
|
||||
|
||||
struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id,
|
||||
uint32_t adv_router,
|
||||
struct ospf6_lsdb *lsdb)
|
||||
|
@ -161,6 +161,12 @@ struct ospf6_route {
|
||||
|
||||
/* nexthop */
|
||||
struct list *nh_list;
|
||||
|
||||
/* points to the summarised route */
|
||||
struct ospf6_external_aggr_rt *aggr_route;
|
||||
|
||||
/* For Aggr routes */
|
||||
bool to_be_processed;
|
||||
};
|
||||
|
||||
#define OSPF6_DEST_TYPE_NONE 0
|
||||
|
@ -409,13 +409,31 @@ static struct ospf6 *ospf6_create(const char *name)
|
||||
|
||||
o->external_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, EXTERNAL_ROUTES);
|
||||
o->external_table->scope = o;
|
||||
|
||||
/* Setting this to 1, so that the LS ID 0 can be considered as invalid
|
||||
* for self originated external LSAs. This helps in differentiating if
|
||||
* an LSA is originated for any route or not in the route data.
|
||||
* rt->route_option->id is by default 0
|
||||
* Consider a route having id as 0 and prefix as 1::1, an external LSA
|
||||
* is originated with ID 0.0.0.0. Now consider another route 2::2
|
||||
* and for this LSA was not originated because of some configuration
|
||||
* but the ID field rt->route_option->id is still 0.Consider now this
|
||||
* 2::2 is being deleted, it will search LSA with LS ID as 0 and it
|
||||
* will find the LSA and hence delete it but the LSA belonged to prefix
|
||||
* 1::1, this happened because of LS ID 0.
|
||||
*/
|
||||
o->external_id = OSPF6_EXT_INIT_LS_ID;
|
||||
o->external_id_table = route_table_init();
|
||||
|
||||
o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
|
||||
o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
|
||||
|
||||
o->distance_table = route_table_init();
|
||||
|
||||
o->rt_aggr_tbl = route_table_init();
|
||||
o->aggr_delay_interval = OSPF6_EXTL_AGGR_DEFAULT_DELAY;
|
||||
o->t_external_aggr = NULL;
|
||||
o->aggr_action = OSPF6_ROUTE_AGGR_NONE;
|
||||
|
||||
o->fd = -1;
|
||||
|
||||
o->max_multipath = MULTIPATH_NUM;
|
||||
@ -461,6 +479,7 @@ struct ospf6 *ospf6_instance_create(const char *name)
|
||||
void ospf6_delete(struct ospf6 *o)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct route_node *rn = NULL;
|
||||
struct ospf6_area *oa;
|
||||
struct vrf *vrf;
|
||||
|
||||
@ -499,6 +518,11 @@ void ospf6_delete(struct ospf6 *o)
|
||||
ospf6_vrf_unlink(o, vrf);
|
||||
}
|
||||
|
||||
for (rn = route_top(o->rt_aggr_tbl); rn; rn = route_next(rn))
|
||||
if (rn->info)
|
||||
ospf6_external_aggregator_free(rn->info);
|
||||
route_table_finish(o->rt_aggr_tbl);
|
||||
|
||||
XFREE(MTYPE_OSPF6_TOP, o->name);
|
||||
XFREE(MTYPE_OSPF6_TOP, o);
|
||||
}
|
||||
@ -527,6 +551,7 @@ static void ospf6_disable(struct ospf6 *o)
|
||||
THREAD_OFF(o->t_ase_calc);
|
||||
THREAD_OFF(o->t_distribute_update);
|
||||
THREAD_OFF(o->t_ospf6_receive);
|
||||
THREAD_OFF(o->t_external_aggr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1672,6 +1697,386 @@ DEFUN(show_ipv6_ospf6_route_type_detail, show_ipv6_ospf6_route_type_detail_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
bool ospf6_is_valid_summary_addr(struct vty *vty, struct prefix *p)
|
||||
{
|
||||
struct in6_addr addr_zero;
|
||||
|
||||
memset(&addr_zero, 0, sizeof(struct in6_addr));
|
||||
|
||||
/* Default prefix validation*/
|
||||
if ((is_default_prefix((struct prefix *)p))
|
||||
|| (!memcmp(&p->u.prefix6, &addr_zero, sizeof(struct in6_addr)))) {
|
||||
vty_out(vty, "Default address should not be configured as summary address.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Host route should not be configured as summary address */
|
||||
if (p->prefixlen == IPV6_MAX_PREFIXLEN) {
|
||||
vty_out(vty, "Host route should not be configured as summary address.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* External Route Aggregation */
|
||||
DEFPY (ospf6_external_route_aggregation,
|
||||
ospf6_external_route_aggregation_cmd,
|
||||
"summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)$mtype}]",
|
||||
"External summary address\n"
|
||||
"Specify IPv6 prefix\n"
|
||||
"Router tag \n"
|
||||
"Router tag value\n"
|
||||
"Metric \n"
|
||||
"Advertised metric for this route\n"
|
||||
"OSPFv3 exterior metric type for summarised routes\n"
|
||||
"Set OSPFv3 External Type 1/2 metrics\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
|
||||
|
||||
struct prefix p;
|
||||
int ret = CMD_SUCCESS;
|
||||
p.family = AF_INET6;
|
||||
ret = str2prefix(prefix_str, &p);
|
||||
if (ret == 0) {
|
||||
vty_out(vty, "Malformed prefix\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Apply mask for given prefix. */
|
||||
apply_mask((struct prefix *)&p);
|
||||
|
||||
if (!ospf6_is_valid_summary_addr(vty, &p))
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
if (!tag_str)
|
||||
tag = 0;
|
||||
|
||||
if (!metric_str)
|
||||
metric = -1;
|
||||
|
||||
if (!mtype_str)
|
||||
mtype = DEFAULT_METRIC_TYPE;
|
||||
|
||||
ret = ospf6_external_aggr_config_set(ospf6, &p, tag, metric, mtype);
|
||||
if (ret == OSPF6_FAILURE) {
|
||||
vty_out(vty, "Invalid configuration!!\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY(no_ospf6_external_route_aggregation,
|
||||
no_ospf6_external_route_aggregation_cmd,
|
||||
"no summary-address X:X::X:X/M$prefix [tag (1-4294967295)] [{metric (0-16777215) | metric-type (1-2)}]",
|
||||
NO_STR
|
||||
"External summary address\n"
|
||||
"Specify IPv6 prefix\n"
|
||||
"Router tag\n"
|
||||
"Router tag value\n"
|
||||
"Metric \n"
|
||||
"Advertised metric for this route\n"
|
||||
"OSPFv3 exterior metric type for summarised routes\n"
|
||||
"Set OSPFv3 External Type 1/2 metrics\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
|
||||
|
||||
struct prefix p;
|
||||
int ret = CMD_SUCCESS;
|
||||
|
||||
ret = str2prefix(prefix_str, &p);
|
||||
if (ret == 0) {
|
||||
vty_out(vty, "Malformed prefix\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Apply mask for given prefix. */
|
||||
apply_mask((struct prefix *)&p);
|
||||
|
||||
if (!ospf6_is_valid_summary_addr(vty, &p))
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
ret = ospf6_external_aggr_config_unset(ospf6, &p);
|
||||
if (ret == OSPF6_INVALID)
|
||||
vty_out(vty, "Invalid configuration!!\n");
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (ospf6_external_route_aggregation_no_advertise,
|
||||
ospf6_external_route_aggregation_no_advertise_cmd,
|
||||
"summary-address X:X::X:X/M$prefix no-advertise",
|
||||
"External summary address\n"
|
||||
"Specify IPv6 prefix\n"
|
||||
"Don't advertise summary route \n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
|
||||
|
||||
struct prefix p;
|
||||
int ret = CMD_SUCCESS;
|
||||
|
||||
ret = str2prefix(prefix_str, &p);
|
||||
if (ret == 0) {
|
||||
vty_out(vty, "Malformed prefix\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Apply mask for given prefix. */
|
||||
apply_mask((struct prefix *)&p);
|
||||
|
||||
if (!ospf6_is_valid_summary_addr(vty, &p))
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
ret = ospf6_asbr_external_rt_no_advertise(ospf6, &p);
|
||||
if (ret == OSPF6_INVALID)
|
||||
vty_out(vty, "!!Invalid configuration\n");
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (no_ospf6_external_route_aggregation_no_advertise,
|
||||
no_ospf6_external_route_aggregation_no_advertise_cmd,
|
||||
"no summary-address X:X::X:X/M$prefix no-advertise",
|
||||
NO_STR
|
||||
"External summary address\n"
|
||||
"Specify IPv6 prefix\n"
|
||||
"Adverise summary route to the AS \n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
|
||||
|
||||
struct prefix p;
|
||||
int ret = CMD_SUCCESS;
|
||||
|
||||
ret = str2prefix(prefix_str, &p);
|
||||
if (ret == 0) {
|
||||
vty_out(vty, "Malformed prefix\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Apply mask for given prefix. */
|
||||
apply_mask((struct prefix *)&p);
|
||||
|
||||
if (!ospf6_is_valid_summary_addr(vty, &p))
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
ret = ospf6_asbr_external_rt_advertise(ospf6, &p);
|
||||
if (ret == OSPF6_INVALID)
|
||||
vty_out(vty, "!!Invalid configuration\n");
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (ospf6_route_aggregation_timer,
|
||||
ospf6_route_aggregation_timer_cmd,
|
||||
"aggregation timer (5-1800)",
|
||||
"External route aggregation\n"
|
||||
"Delay timer (in seconds)\n"
|
||||
"Timer interval(in seconds)\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
|
||||
|
||||
ospf6_external_aggr_delay_timer_set(ospf6, timer);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (no_ospf6_route_aggregation_timer,
|
||||
no_ospf6_route_aggregation_timer_cmd,
|
||||
"no aggregation timer [5-1800]",
|
||||
NO_STR
|
||||
"External route aggregation\n"
|
||||
"Delay timer\n"
|
||||
"Timer interval(in seconds)\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
|
||||
|
||||
ospf6_external_aggr_delay_timer_set(ospf6,
|
||||
OSPF6_EXTL_AGGR_DEFAULT_DELAY);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_print_vty_external_routes_walkcb(struct hash_bucket *bucket, void *arg)
|
||||
{
|
||||
struct ospf6_route *rt = bucket->data;
|
||||
struct vty *vty = (struct vty *)arg;
|
||||
static unsigned int count;
|
||||
|
||||
vty_out(vty, "%pFX ", &rt->prefix);
|
||||
|
||||
count++;
|
||||
|
||||
if (count%5 == 0)
|
||||
vty_out(vty, "\n");
|
||||
|
||||
if (OSPF6_EXTERNAL_RT_COUNT(rt->aggr_route) == count)
|
||||
count = 0;
|
||||
|
||||
return HASHWALK_CONTINUE;
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_print_json_external_routes_walkcb(struct hash_bucket *bucket, void *arg)
|
||||
{
|
||||
struct ospf6_route *rt = bucket->data;
|
||||
struct json_object *json = (struct json_object *)arg;
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
char exnalbuf[20];
|
||||
static unsigned int count;
|
||||
|
||||
prefix2str(&rt->prefix, buf, sizeof(buf));
|
||||
|
||||
snprintf(exnalbuf, 20, "Exnl Addr-%d", count);
|
||||
|
||||
json_object_string_add(json, exnalbuf, buf);
|
||||
|
||||
count++;
|
||||
|
||||
if (OSPF6_EXTERNAL_RT_COUNT(rt->aggr_route) == count)
|
||||
count = 0;
|
||||
|
||||
return HASHWALK_CONTINUE;
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_show_summary_address(struct vty *vty, struct ospf6 *ospf6,
|
||||
json_object *json,
|
||||
bool uj, const char *detail)
|
||||
{
|
||||
struct route_node *rn;
|
||||
static char header[] = "Summary-address Metric-type Metric Tag External_Rt_count\n";
|
||||
|
||||
if (!uj) {
|
||||
vty_out(vty, "aggregation delay interval :%d(in seconds)\n\n",
|
||||
ospf6->aggr_delay_interval);
|
||||
vty_out(vty, "%s\n", header);
|
||||
}
|
||||
else
|
||||
json_object_int_add(json, "aggregation delay interval",
|
||||
ospf6->aggr_delay_interval);
|
||||
|
||||
for (rn = route_top(ospf6->rt_aggr_tbl); rn; rn = route_next(rn))
|
||||
if (rn->info) {
|
||||
struct ospf6_external_aggr_rt *aggr = rn->info;
|
||||
json_object *json_aggr = NULL;
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
|
||||
prefix2str(&aggr->p, buf, sizeof(buf));
|
||||
|
||||
if (uj) {
|
||||
|
||||
json_aggr = json_object_new_object();
|
||||
|
||||
json_object_object_add(json,
|
||||
buf,
|
||||
json_aggr);
|
||||
|
||||
json_object_string_add(json_aggr,
|
||||
"Summary address",
|
||||
buf);
|
||||
|
||||
json_object_string_add(
|
||||
json_aggr, "Metric-type",
|
||||
(aggr->mtype == DEFAULT_METRIC_TYPE)
|
||||
? "E2"
|
||||
: "E1");
|
||||
|
||||
json_object_int_add(json_aggr, "Metric",
|
||||
(aggr->metric != -1)
|
||||
? aggr->metric
|
||||
: DEFAULT_DEFAULT_METRIC);
|
||||
|
||||
json_object_int_add(json_aggr, "Tag",
|
||||
aggr->tag);
|
||||
|
||||
json_object_int_add(json_aggr,
|
||||
"External route count",
|
||||
OSPF6_EXTERNAL_RT_COUNT(aggr));
|
||||
|
||||
if (OSPF6_EXTERNAL_RT_COUNT(aggr) && detail) {
|
||||
json_object_int_add(json_aggr, "ID",
|
||||
aggr->id);
|
||||
json_object_int_add(json_aggr, "Flags",
|
||||
aggr->aggrflags);
|
||||
hash_walk(aggr->match_extnl_hash,
|
||||
ospf6_print_json_external_routes_walkcb,
|
||||
json_aggr);
|
||||
}
|
||||
|
||||
} else {
|
||||
vty_out(vty, "%-22s", buf);
|
||||
|
||||
(aggr->mtype == DEFAULT_METRIC_TYPE)
|
||||
? vty_out(vty, "%-16s", "E2")
|
||||
: vty_out(vty, "%-16s", "E1");
|
||||
vty_out(vty, "%-11d", (aggr->metric != -1)
|
||||
? aggr->metric
|
||||
: DEFAULT_DEFAULT_METRIC);
|
||||
|
||||
vty_out(vty, "%-12u", aggr->tag);
|
||||
|
||||
vty_out(vty, "%-5ld\n",
|
||||
OSPF6_EXTERNAL_RT_COUNT(aggr));
|
||||
|
||||
if (OSPF6_EXTERNAL_RT_COUNT(aggr) && detail) {
|
||||
vty_out(vty,
|
||||
"Matched External routes:\n");
|
||||
hash_walk(aggr->match_extnl_hash,
|
||||
ospf6_print_vty_external_routes_walkcb,
|
||||
vty);
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (show_ipv6_ospf6_external_aggregator,
|
||||
show_ipv6_ospf6_external_aggregator_cmd,
|
||||
"show ipv6 ospf6 summary-address [detail$detail] [json]",
|
||||
SHOW_STR
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Show external summary addresses\n"
|
||||
"detailed informtion\n"
|
||||
JSON_STR)
|
||||
{
|
||||
bool uj = use_json(argc, argv);
|
||||
struct ospf6 *ospf6 = NULL;
|
||||
json_object *json = NULL;
|
||||
|
||||
if (uj)
|
||||
json = json_object_new_object();
|
||||
|
||||
/* Default Vrf */
|
||||
ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
|
||||
if (ospf6 == NULL) {
|
||||
if (uj) {
|
||||
vty_out(vty, "%s\n",
|
||||
json_object_to_json_string_ext(
|
||||
json, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_free(json);
|
||||
} else
|
||||
vty_out(vty, "OSPFv3 is not running\n");
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ospf6_show_summary_address(vty, ospf6, json, uj, detail);
|
||||
|
||||
if (uj) {
|
||||
vty_out(vty, "%s\n",json_object_to_json_string_ext(
|
||||
json, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_free(json);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void ospf6_stub_router_config_write(struct vty *vty, struct ospf6 *ospf6)
|
||||
{
|
||||
if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
|
||||
@ -1711,6 +2116,41 @@ static int ospf6_distance_config_write(struct vty *vty, struct ospf6 *ospf6)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ospf6_asbr_summary_config_write(struct vty *vty, struct ospf6 *ospf6)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct ospf6_external_aggr_rt *aggr;
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
|
||||
if (ospf6->aggr_delay_interval != OSPF6_EXTL_AGGR_DEFAULT_DELAY)
|
||||
vty_out(vty, " aggregation timer %u\n",
|
||||
ospf6->aggr_delay_interval);
|
||||
|
||||
/* print 'summary-address A:B::C:D/M' */
|
||||
for (rn = route_top(ospf6->rt_aggr_tbl); rn; rn = route_next(rn))
|
||||
if (rn->info) {
|
||||
aggr = rn->info;
|
||||
prefix2str(&aggr->p, buf, sizeof(buf));
|
||||
vty_out(vty, " summary-address %s ", buf);
|
||||
if (aggr->tag)
|
||||
vty_out(vty, " tag %u ", aggr->tag);
|
||||
|
||||
if (aggr->metric != -1)
|
||||
vty_out(vty, " metric %d ", aggr->metric);
|
||||
|
||||
if (aggr->mtype != DEFAULT_METRIC_TYPE)
|
||||
vty_out(vty, " metric-type %d ", aggr->mtype);
|
||||
|
||||
if (CHECK_FLAG(aggr->aggrflags,
|
||||
OSPF6_EXTERNAL_AGGRT_NO_ADVERTISE))
|
||||
vty_out(vty, " no-advertise");
|
||||
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* OSPF configuration write function. */
|
||||
static int config_write_ospf6(struct vty *vty)
|
||||
{
|
||||
@ -1768,6 +2208,7 @@ static int config_write_ospf6(struct vty *vty)
|
||||
ospf6_spf_config_write(vty, ospf6);
|
||||
ospf6_distance_config_write(vty, ospf6);
|
||||
ospf6_distribute_config_write(vty, ospf6);
|
||||
ospf6_asbr_summary_config_write(vty, ospf6);
|
||||
|
||||
vty_out(vty, "!\n");
|
||||
}
|
||||
@ -1826,6 +2267,17 @@ void ospf6_top_init(void)
|
||||
install_element(OSPF6_NODE, &ospf6_max_multipath_cmd);
|
||||
install_element(OSPF6_NODE, &no_ospf6_max_multipath_cmd);
|
||||
|
||||
/* ASBR Summarisation */
|
||||
install_element(OSPF6_NODE, &ospf6_external_route_aggregation_cmd);
|
||||
install_element(OSPF6_NODE, &no_ospf6_external_route_aggregation_cmd);
|
||||
install_element(OSPF6_NODE,
|
||||
&ospf6_external_route_aggregation_no_advertise_cmd);
|
||||
install_element(OSPF6_NODE,
|
||||
&no_ospf6_external_route_aggregation_no_advertise_cmd);
|
||||
install_element(OSPF6_NODE, &ospf6_route_aggregation_timer_cmd);
|
||||
install_element(OSPF6_NODE, &no_ospf6_route_aggregation_timer_cmd);
|
||||
install_element(VIEW_NODE, &show_ipv6_ospf6_external_aggregator_cmd);
|
||||
|
||||
install_element(OSPF6_NODE, &ospf6_distance_cmd);
|
||||
install_element(OSPF6_NODE, &no_ospf6_distance_cmd);
|
||||
install_element(OSPF6_NODE, &ospf6_distance_ospf6_cmd);
|
||||
|
@ -91,6 +91,7 @@ struct ospf6 {
|
||||
|
||||
struct ospf6_route_table *external_table;
|
||||
struct route_table *external_id_table;
|
||||
#define OSPF6_EXT_INIT_LS_ID 1
|
||||
uint32_t external_id;
|
||||
|
||||
/* OSPF6 redistribute configuration */
|
||||
@ -130,6 +131,7 @@ struct ospf6 {
|
||||
struct thread *maxage_remover;
|
||||
struct thread *t_distribute_update; /* Distirbute update timer. */
|
||||
struct thread *t_ospf6_receive; /* OSPF6 receive timer */
|
||||
struct thread *t_external_aggr; /* OSPF6 aggregation timer */
|
||||
#define OSPF6_WRITE_INTERFACE_COUNT_DEFAULT 20
|
||||
struct thread *t_write;
|
||||
|
||||
@ -158,6 +160,16 @@ struct ospf6 {
|
||||
struct list *oi_write_q;
|
||||
|
||||
uint32_t redist_count;
|
||||
|
||||
/* Action for aggregation of external LSAs */
|
||||
int aggr_action;
|
||||
|
||||
#define OSPF6_EXTL_AGGR_DEFAULT_DELAY 5
|
||||
/* For ASBR summary delay timer */
|
||||
int aggr_delay_interval;
|
||||
/* Table of configured Aggregate addresses */
|
||||
struct route_table *rt_aggr_tbl;
|
||||
|
||||
QOBJ_FIELDS;
|
||||
};
|
||||
DECLARE_QOBJ_TYPE(ospf6);
|
||||
@ -188,4 +200,5 @@ struct ospf6 *ospf6_lookup_by_vrf_id(vrf_id_t vrf_id);
|
||||
struct ospf6 *ospf6_lookup_by_vrf_name(const char *name);
|
||||
const char *ospf6_vrf_id_to_name(vrf_id_t vrf_id);
|
||||
void ospf6_vrf_init(void);
|
||||
bool ospf6_is_valid_summary_addr(struct vty *vty, struct prefix *p);
|
||||
#endif /* OSPF6_TOP_H */
|
||||
|
@ -49,6 +49,10 @@ extern struct thread_master *master;
|
||||
#define MSG_OK 0
|
||||
#define MSG_NG 1
|
||||
|
||||
#define OSPF6_SUCCESS 1
|
||||
#define OSPF6_FAILURE 0
|
||||
#define OSPF6_INVALID -1
|
||||
|
||||
/* cast macro: XXX - these *must* die, ick ick. */
|
||||
#define OSPF6_PROCESS(x) ((struct ospf6 *) (x))
|
||||
#define OSPF6_AREA(x) ((struct ospf6_area *) (x))
|
||||
|
@ -90,6 +90,7 @@ ospf6d_ospf6d_snmp_la_LIBADD = lib/libfrrsnmp.la
|
||||
clippy_scan += \
|
||||
ospf6d/ospf6_top.c \
|
||||
ospf6d/ospf6_asbr.c \
|
||||
ospf6d/ospf6_lsa.c \
|
||||
# end
|
||||
|
||||
nodist_ospf6d_ospf6d_SOURCES = \
|
||||
|
Loading…
Reference in New Issue
Block a user