summaryrefslogtreecommitdiff
path: root/ospfd
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd')
-rw-r--r--ospfd/ospf_abr.c324
-rw-r--r--ospfd/ospf_abr.h25
-rw-r--r--ospfd/ospf_interface.c28
-rw-r--r--ospfd/ospf_interface.h3
-rw-r--r--ospfd/ospf_lsa.c128
-rw-r--r--ospfd/ospf_lsa.h5
-rw-r--r--ospfd/ospf_network.c136
-rw-r--r--ospfd/ospf_network.h15
-rw-r--r--ospfd/ospf_packet.c23
-rw-r--r--ospfd/ospf_route.c14
-rw-r--r--ospfd/ospf_route.h5
-rw-r--r--ospfd/ospf_routemap.c8
-rw-r--r--ospfd/ospf_snmp.c2
-rw-r--r--ospfd/ospf_te.c20
-rw-r--r--ospfd/ospf_vty.c504
-rw-r--r--ospfd/ospf_zebra.c57
-rw-r--r--ospfd/ospf_zebra.h1
-rw-r--r--ospfd/ospfd.c118
-rw-r--r--ospfd/ospfd.h41
19 files changed, 1060 insertions, 397 deletions
diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c
index e14586c5ee..ded520889f 100644
--- a/ospfd/ospf_abr.c
+++ b/ospfd/ospf_abr.c
@@ -54,6 +54,7 @@ static void ospf_area_range_free(struct ospf_area_range *range)
}
static void ospf_area_range_add(struct ospf_area *area,
+ struct route_table *ranges,
struct ospf_area_range *range)
{
struct route_node *rn;
@@ -64,7 +65,7 @@ static void ospf_area_range_add(struct ospf_area *area,
p.prefix = range->addr;
apply_mask_ipv4(&p);
- rn = route_node_get(area->ranges, (struct prefix *)&p);
+ rn = route_node_get(ranges, (struct prefix *)&p);
if (rn->info)
route_unlock_node(rn);
else
@@ -75,10 +76,12 @@ static void ospf_area_range_delete(struct ospf_area *area,
struct route_node *rn)
{
struct ospf_area_range *range = rn->info;
+ bool nssa = CHECK_FLAG(range->flags, OSPF_AREA_RANGE_NSSA);
- if (range->specifics != 0)
+ if (ospf_area_range_active(range) &&
+ CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE))
ospf_delete_discard_route(area->ospf, area->ospf->new_table,
- (struct prefix_ipv4 *)&rn->p);
+ (struct prefix_ipv4 *)&rn->p, nssa);
ospf_area_range_free(range);
rn->info = NULL;
@@ -87,11 +90,12 @@ static void ospf_area_range_delete(struct ospf_area *area,
}
struct ospf_area_range *ospf_area_range_lookup(struct ospf_area *area,
+ struct route_table *ranges,
struct prefix_ipv4 *p)
{
struct route_node *rn;
- rn = route_node_lookup(area->ranges, (struct prefix *)p);
+ rn = route_node_lookup(ranges, (struct prefix *)p);
if (rn) {
route_unlock_node(rn);
return rn->info;
@@ -133,11 +137,12 @@ struct ospf_area_range *ospf_area_range_lookup_next(struct ospf_area *area,
}
static struct ospf_area_range *ospf_area_range_match(struct ospf_area *area,
+ struct route_table *ranges,
struct prefix_ipv4 *p)
{
struct route_node *node;
- node = route_node_match(area->ranges, (struct prefix *)p);
+ node = route_node_match(ranges, (struct prefix *)p);
if (node) {
route_unlock_node(node);
return node->info;
@@ -153,7 +158,7 @@ struct ospf_area_range *ospf_area_range_match_any(struct ospf *ospf,
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
- if ((range = ospf_area_range_match(area, p)))
+ if ((range = ospf_area_range_match(area, area->ranges, p)))
return range;
return NULL;
@@ -169,17 +174,13 @@ static int ospf_area_actively_attached(struct ospf_area *area)
return area->act_ints;
}
-int ospf_area_range_set(struct ospf *ospf, struct in_addr area_id,
- struct prefix_ipv4 *p, int advertise)
+int ospf_area_range_set(struct ospf *ospf, struct ospf_area *area,
+ struct route_table *ranges, struct prefix_ipv4 *p,
+ int advertise, bool nssa)
{
- struct ospf_area *area;
struct ospf_area_range *range;
- area = ospf_area_get(ospf, area_id);
- if (area == NULL)
- return 0;
-
- range = ospf_area_range_lookup(area, p);
+ range = ospf_area_range_lookup(area, ranges, p);
if (range != NULL) {
if (!CHECK_FLAG(advertise, OSPF_AREA_RANGE_ADVERTISE))
range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC;
@@ -190,7 +191,7 @@ int ospf_area_range_set(struct ospf *ospf, struct in_addr area_id,
ospf_schedule_abr_task(ospf);
} else {
range = ospf_area_range_new(p);
- ospf_area_range_add(area, range);
+ ospf_area_range_add(area, ranges, range);
ospf_schedule_abr_task(ospf);
}
@@ -201,20 +202,19 @@ int ospf_area_range_set(struct ospf *ospf, struct in_addr area_id,
range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC;
}
+ if (nssa)
+ SET_FLAG(range->flags, OSPF_AREA_RANGE_NSSA);
+
return 1;
}
-int ospf_area_range_cost_set(struct ospf *ospf, struct in_addr area_id,
- struct prefix_ipv4 *p, uint32_t cost)
+int ospf_area_range_cost_set(struct ospf *ospf, struct ospf_area *area,
+ struct route_table *ranges, struct prefix_ipv4 *p,
+ uint32_t cost)
{
- struct ospf_area *area;
struct ospf_area_range *range;
- area = ospf_area_get(ospf, area_id);
- if (area == NULL)
- return 0;
-
- range = ospf_area_range_lookup(area, p);
+ range = ospf_area_range_lookup(area, ranges, p);
if (range == NULL)
return 0;
@@ -227,17 +227,12 @@ int ospf_area_range_cost_set(struct ospf *ospf, struct in_addr area_id,
return 1;
}
-int ospf_area_range_unset(struct ospf *ospf, struct in_addr area_id,
- struct prefix_ipv4 *p)
+int ospf_area_range_unset(struct ospf *ospf, struct ospf_area *area,
+ struct route_table *ranges, struct prefix_ipv4 *p)
{
- struct ospf_area *area;
struct route_node *rn;
- area = ospf_area_lookup_by_area_id(ospf, area_id);
- if (area == NULL)
- return 0;
-
- rn = route_node_lookup(area->ranges, (struct prefix *)p);
+ rn = route_node_lookup(ranges, (struct prefix *)p);
if (rn == NULL)
return 0;
@@ -249,14 +244,12 @@ int ospf_area_range_unset(struct ospf *ospf, struct in_addr area_id,
return 1;
}
-int ospf_area_range_substitute_set(struct ospf *ospf, struct in_addr area_id,
+int ospf_area_range_substitute_set(struct ospf *ospf, struct ospf_area *area,
struct prefix_ipv4 *p, struct prefix_ipv4 *s)
{
- struct ospf_area *area;
struct ospf_area_range *range;
- area = ospf_area_get(ospf, area_id);
- range = ospf_area_range_lookup(area, p);
+ range = ospf_area_range_lookup(area, area->ranges, p);
if (range != NULL) {
if (!CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE)
@@ -264,7 +257,7 @@ int ospf_area_range_substitute_set(struct ospf *ospf, struct in_addr area_id,
ospf_schedule_abr_task(ospf);
} else {
range = ospf_area_range_new(p);
- ospf_area_range_add(area, range);
+ ospf_area_range_add(area, area->ranges, range);
ospf_schedule_abr_task(ospf);
}
@@ -276,17 +269,12 @@ int ospf_area_range_substitute_set(struct ospf *ospf, struct in_addr area_id,
return 1;
}
-int ospf_area_range_substitute_unset(struct ospf *ospf, struct in_addr area_id,
+int ospf_area_range_substitute_unset(struct ospf *ospf, struct ospf_area *area,
struct prefix_ipv4 *p)
{
- struct ospf_area *area;
struct ospf_area_range *range;
- area = ospf_area_lookup_by_area_id(ospf, area_id);
- if (area == NULL)
- return 0;
-
- range = ospf_area_range_lookup(area, p);
+ range = ospf_area_range_lookup(area, area->ranges, p);
if (range == NULL)
return 0;
@@ -538,8 +526,7 @@ void ospf_check_abr_status(struct ospf *ospf)
}
static void ospf_abr_update_aggregate(struct ospf_area_range *range,
- struct ospf_route * or,
- struct ospf_area *area)
+ uint32_t cost, struct ospf_area *area)
{
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: Start", __func__);
@@ -557,20 +544,18 @@ static void ospf_abr_update_aggregate(struct ospf_area_range *range,
range->cost = range->cost_config;
} else {
- if (range->specifics == 0) {
+ if (!ospf_area_range_active(range)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("%s: use or->cost %d", __func__,
- or->cost);
+ zlog_debug("%s: use cost %d", __func__, cost);
- range->cost = or->cost; /* 1st time get 1st cost */
+ range->cost = cost; /* 1st time get 1st cost */
}
- if (or->cost > range->cost) {
+ if (cost > range->cost) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("%s: update to %d", __func__,
- or->cost);
+ zlog_debug("%s: update to %d", __func__, cost);
- range->cost = or->cost;
+ range->cost = cost;
}
}
@@ -605,6 +590,7 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
struct ospf_lsa *old = NULL, *new = NULL;
struct as_external_lsa *ext7;
struct prefix_ipv4 p;
+ struct ospf_area_range *range;
if (!CHECK_FLAG(lsa->data->options, OSPF_OPTION_NP)) {
if (IS_DEBUG_OSPF_NSSA)
@@ -646,6 +632,18 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
return 1;
}
+ range = ospf_area_range_match(area, area->nssa_ranges, &p);
+ if (range) {
+ if (IS_DEBUG_OSPF_NSSA)
+ zlog_debug("Suppressed by range %pI4/%u of area %pI4",
+ &range->addr, range->masklen,
+ &area->area_id);
+
+ ospf_abr_update_aggregate(range, GET_METRIC(ext7->e[0].metric),
+ area);
+ return 1;
+ }
+
if (old && CHECK_FLAG(old->flags, OSPF_LSA_APPROVED)) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
@@ -675,17 +673,27 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
}
}
- /* Area where Aggregate testing will be inserted, just like summary
- advertisements */
- /* ospf_abr_check_nssa_range (p_arg, lsa-> cost, lsa -> area); */
-
return 0;
}
-static void ospf_abr_translate_nssa_range(struct prefix_ipv4 *p, uint32_t cost)
+static void ospf_abr_translate_nssa_range(struct ospf *ospf,
+ struct prefix_ipv4 *p, uint32_t cost)
{
- /* The Type-7 is created from the aggregated prefix and forwarded
- for lsa installation and flooding... to be added... */
+ struct external_info ei = {};
+ struct ospf_lsa *lsa;
+
+ prefix_copy(&ei.p, p);
+ ei.type = ZEBRA_ROUTE_OSPF;
+ ei.route_map_set.metric = cost;
+ ei.route_map_set.metric_type = -1;
+
+ lsa = ospf_external_info_find_lsa(ospf, p);
+ if (lsa)
+ lsa = ospf_external_lsa_refresh(ospf, lsa, &ei,
+ LSA_REFRESH_FORCE, true);
+ else
+ lsa = ospf_external_lsa_originate(ospf, &ei);
+ SET_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT);
}
void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost,
@@ -892,9 +900,11 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p,
zlog_debug(
"%s: this is intra-area route to %pFX",
__func__, p);
- if ((range = ospf_area_range_match(or_area, p))
- && !ospf_area_is_transit(area))
- ospf_abr_update_aggregate(range, or, area);
+ if ((range = ospf_area_range_match(
+ or_area, or_area->ranges, p)) &&
+ !ospf_area_is_transit(area))
+ ospf_abr_update_aggregate(range, or->cost,
+ area);
else
ospf_abr_announce_network_to_area(p, or->cost,
area);
@@ -1345,7 +1355,7 @@ static void ospf_abr_unapprove_summaries(struct ospf *ospf)
zlog_debug("%s: Stop", __func__);
}
-static void ospf_abr_prepare_aggregates(struct ospf *ospf)
+static void ospf_abr_prepare_aggregates(struct ospf *ospf, bool nssa)
{
struct listnode *node;
struct route_node *rn;
@@ -1356,7 +1366,14 @@ static void ospf_abr_prepare_aggregates(struct ospf *ospf)
zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
- for (rn = route_top(area->ranges); rn; rn = route_next(rn))
+ struct route_table *ranges;
+
+ if (nssa)
+ ranges = area->nssa_ranges;
+ else
+ ranges = area->ranges;
+
+ for (rn = route_top(ranges); rn; rn = route_next(rn))
if ((range = rn->info) != NULL) {
range->cost = 0;
range->specifics = 0;
@@ -1409,7 +1426,7 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf)
p.prefixlen = range->subst_masklen;
}
- if (range->specifics) {
+ if (ospf_area_range_active(range)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: active range",
__func__);
@@ -1452,13 +1469,11 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf)
zlog_debug("%s: Stop", __func__);
}
-static void
-ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
+static void ospf_abr_send_nssa_aggregates(struct ospf *ospf)
{
- struct listnode *node; /*, n; */
- struct ospf_area *area; /*, *ar; */
+ struct listnode *node;
+ struct ospf_area *area;
struct route_node *rn;
- struct ospf_area_range *range;
struct prefix_ipv4 p;
if (IS_DEBUG_OSPF_NSSA)
@@ -1472,20 +1487,13 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
zlog_debug("%s: looking at area %pI4", __func__,
&area->area_id);
- for (rn = route_top(area->ranges); rn; rn = route_next(rn)) {
- if (rn->info == NULL)
- continue;
+ for (rn = route_top(area->nssa_ranges); rn;
+ rn = route_next(rn)) {
+ struct ospf_area_range *range;
range = rn->info;
-
- if (!CHECK_FLAG(range->flags,
- OSPF_AREA_RANGE_ADVERTISE)) {
- if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "%s: discarding suppress-ranges",
- __func__);
+ if (!range)
continue;
- }
p.family = AF_INET;
p.prefix = range->addr;
@@ -1495,14 +1503,9 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
zlog_debug("%s: this is range: %pFX", __func__,
&p);
- if (CHECK_FLAG(range->flags,
- OSPF_AREA_RANGE_SUBSTITUTE)) {
- p.family = AF_INET;
- p.prefix = range->subst_addr;
- p.prefixlen = range->subst_masklen;
- }
-
- if (range->specifics) {
+ if (ospf_area_range_active(range)
+ && CHECK_FLAG(range->flags,
+ OSPF_AREA_RANGE_ADVERTISE)) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug("%s: active range",
__func__);
@@ -1512,7 +1515,8 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
* translate, Install (as Type-5), Approve, and
* Flood
*/
- ospf_abr_translate_nssa_range(&p, range->cost);
+ ospf_abr_translate_nssa_range(ospf, &p,
+ range->cost);
}
} /* all area ranges*/
} /* all areas */
@@ -1807,6 +1811,82 @@ static void ospf_abr_announce_non_dna_routers(struct event *thread)
OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, "%s(): Stop", __func__);
}
+static void ospf_abr_nssa_type7_default_create(struct ospf *ospf,
+ struct ospf_area *area,
+ struct ospf_lsa *lsa)
+{
+ struct external_info ei;
+
+ if (IS_DEBUG_OSPF_NSSA)
+ zlog_debug(
+ "Announcing Type-7 default route into NSSA area %pI4",
+ &area->area_id);
+
+ /* Prepare the extrenal_info for aggregator */
+ memset(&ei, 0, sizeof(struct external_info));
+ ei.p.family = AF_INET;
+ ei.p.prefixlen = 0;
+ ei.tag = 0;
+ ei.type = 0;
+ ei.instance = ospf->instance;
+
+ /* Compute default route type and metric. */
+ if (area->nssa_default_originate.metric_value != -1)
+ ei.route_map_set.metric =
+ area->nssa_default_originate.metric_value;
+ else
+ ei.route_map_set.metric = DEFAULT_DEFAULT_ALWAYS_METRIC;
+ if (area->nssa_default_originate.metric_type != -1)
+ ei.route_map_set.metric_type =
+ area->nssa_default_originate.metric_type;
+ else
+ ei.route_map_set.metric_type = DEFAULT_METRIC_TYPE;
+
+ if (!lsa)
+ ospf_nssa_lsa_originate(area, &ei);
+ else
+ ospf_nssa_lsa_refresh(area, lsa, &ei);
+}
+
+static void ospf_abr_nssa_type7_default_delete(struct ospf *ospf,
+ struct ospf_area *area,
+ struct ospf_lsa *lsa)
+{
+ if (lsa && !CHECK_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE)) {
+ if (IS_DEBUG_OSPF_NSSA)
+ zlog_debug(
+ "Withdrawing Type-7 default route from area %pI4",
+ &area->area_id);
+
+ ospf_ls_retransmit_delete_nbr_area(area, lsa);
+ ospf_refresher_unregister_lsa(ospf, lsa);
+ ospf_lsa_flush_area(lsa, area);
+ }
+}
+
+/* NSSA Type-7 default route. */
+void ospf_abr_nssa_type7_defaults(struct ospf *ospf)
+{
+ struct ospf_area *area;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
+ struct in_addr id = {};
+ struct ospf_lsa *lsa;
+
+ lsa = ospf_lsdb_lookup_by_id(area->lsdb, OSPF_AS_NSSA_LSA, id,
+ area->ospf->router_id);
+ if (area->external_routing == OSPF_AREA_NSSA
+ && area->nssa_default_originate.enabled
+ && (IS_OSPF_ABR(ospf)
+ || (IS_OSPF_ASBR(ospf)
+ && ospf->nssa_default_import_check.status)))
+ ospf_abr_nssa_type7_default_create(ospf, area, lsa);
+ else
+ ospf_abr_nssa_type7_default_delete(ospf, area, lsa);
+ }
+}
+
static int ospf_abr_remove_unapproved_translates_apply(struct ospf *ospf,
struct ospf_lsa *lsa)
{
@@ -1874,30 +1954,39 @@ static void ospf_abr_remove_unapproved_summaries(struct ospf *ospf)
zlog_debug("%s: Stop", __func__);
}
-static void ospf_abr_manage_discard_routes(struct ospf *ospf)
+static void ospf_abr_manage_discard_routes(struct ospf *ospf, bool nssa)
{
struct listnode *node, *nnode;
struct route_node *rn;
struct ospf_area *area;
- struct ospf_area_range *range;
- for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
- for (rn = route_top(area->ranges); rn; rn = route_next(rn))
- if ((range = rn->info) != NULL)
- if (CHECK_FLAG(range->flags,
- OSPF_AREA_RANGE_ADVERTISE)) {
- if (range->specifics)
- ospf_add_discard_route(
- ospf, ospf->new_table,
- area,
- (struct prefix_ipv4
- *)&rn->p);
- else
- ospf_delete_discard_route(
- ospf, ospf->new_table,
- (struct prefix_ipv4
- *)&rn->p);
- }
+ for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
+ struct route_table *ranges;
+
+ if (nssa)
+ ranges = area->nssa_ranges;
+ else
+ ranges = area->ranges;
+
+ for (rn = route_top(ranges); rn; rn = route_next(rn)) {
+ struct ospf_area_range *range;
+
+ range = rn->info;
+ if (!range)
+ continue;
+
+ if (ospf_area_range_active(range)
+ && CHECK_FLAG(range->flags,
+ OSPF_AREA_RANGE_ADVERTISE))
+ ospf_add_discard_route(
+ ospf, ospf->new_table, area,
+ (struct prefix_ipv4 *)&rn->p, nssa);
+ else
+ ospf_delete_discard_route(
+ ospf, ospf->new_table,
+ (struct prefix_ipv4 *)&rn->p, nssa);
+ }
+ }
}
/* This is the function taking care about ABR NSSA, i.e. NSSA
@@ -1925,7 +2014,7 @@ static void ospf_abr_manage_discard_routes(struct ospf *ospf)
For External Calculations, any NSSA areas use the Type-7 AREA-LSDB,
any ABR-non-NSSA areas use the Type-5 GLOBAL-LSDB. */
-static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
+void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
{
if (ospf->gr_info.restart_in_progress)
return;
@@ -1952,7 +2041,7 @@ static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
/* RESET all Ranges in every Area, same as summaries */
if (IS_DEBUG_OSPF_NSSA)
zlog_debug("%s: NSSA initialize aggregates", __func__);
- ospf_abr_prepare_aggregates(ospf); /*TURNED OFF just for now */
+ ospf_abr_prepare_aggregates(ospf, true);
/* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
* Aggregate as Type-7
@@ -1983,7 +2072,7 @@ static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
zlog_debug("%s: remove unapproved translates", __func__);
ospf_abr_remove_unapproved_translates(ospf);
- ospf_abr_manage_discard_routes(ospf); /* same as normal...discard */
+ ospf_abr_manage_discard_routes(ospf, true);
if (IS_DEBUG_OSPF_NSSA)
zlog_debug("%s: Stop", __func__);
@@ -2012,7 +2101,7 @@ void ospf_abr_task(struct ospf *ospf)
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: prepare aggregates", __func__);
- ospf_abr_prepare_aggregates(ospf);
+ ospf_abr_prepare_aggregates(ospf, false);
if (IS_OSPF_ABR(ospf)) {
if (IS_DEBUG_OSPF_EVENT)
@@ -2031,6 +2120,11 @@ void ospf_abr_task(struct ospf *ospf)
zlog_debug("%s: announce stub defaults", __func__);
ospf_abr_announce_stub_defaults(ospf);
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("%s: announce NSSA Type-7 defaults",
+ __func__);
+ ospf_abr_nssa_type7_defaults(ospf);
+
if (ospf->fr_configured) {
OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT,
"%s(): announce non-DNArouters",
@@ -2050,7 +2144,7 @@ void ospf_abr_task(struct ospf *ospf)
zlog_debug("%s: remove unapproved summaries", __func__);
ospf_abr_remove_unapproved_summaries(ospf);
- ospf_abr_manage_discard_routes(ospf);
+ ospf_abr_manage_discard_routes(ospf, false);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: Stop", __func__);
diff --git a/ospfd/ospf_abr.h b/ospfd/ospf_abr.h
index 19d444b125..cc2b2b0548 100644
--- a/ospfd/ospf_abr.h
+++ b/ospfd/ospf_abr.h
@@ -16,6 +16,7 @@
#define OSPF_AREA_RANGE_ADVERTISE (1 << 0)
#define OSPF_AREA_RANGE_SUBSTITUTE (1 << 1)
+#define OSPF_AREA_RANGE_NSSA (1 << 2)
/* Area range. */
struct ospf_area_range {
@@ -44,23 +45,23 @@ struct ospf_area_range {
/* Prototypes. */
extern struct ospf_area_range *ospf_area_range_lookup(struct ospf_area *,
+ struct route_table *,
struct prefix_ipv4 *);
-
-extern struct ospf_area_range *ospf_some_area_range_match(struct prefix_ipv4 *);
-
extern struct ospf_area_range *
ospf_area_range_lookup_next(struct ospf_area *, struct in_addr *, int);
-extern int ospf_area_range_set(struct ospf *, struct in_addr,
- struct prefix_ipv4 *, int);
-extern int ospf_area_range_cost_set(struct ospf *, struct in_addr,
- struct prefix_ipv4 *, uint32_t);
-extern int ospf_area_range_unset(struct ospf *, struct in_addr,
- struct prefix_ipv4 *);
-extern int ospf_area_range_substitute_set(struct ospf *, struct in_addr,
+extern int ospf_area_range_set(struct ospf *, struct ospf_area *,
+ struct route_table *, struct prefix_ipv4 *, int,
+ bool);
+extern int ospf_area_range_cost_set(struct ospf *, struct ospf_area *,
+ struct route_table *, struct prefix_ipv4 *,
+ uint32_t);
+extern int ospf_area_range_unset(struct ospf *, struct ospf_area *,
+ struct route_table *, struct prefix_ipv4 *);
+extern int ospf_area_range_substitute_set(struct ospf *, struct ospf_area *,
struct prefix_ipv4 *,
struct prefix_ipv4 *);
-extern int ospf_area_range_substitute_unset(struct ospf *, struct in_addr,
+extern int ospf_area_range_substitute_unset(struct ospf *, struct ospf_area *,
struct prefix_ipv4 *);
extern struct ospf_area_range *ospf_area_range_match_any(struct ospf *,
struct prefix_ipv4 *);
@@ -69,10 +70,12 @@ extern int ospf_act_bb_connection(struct ospf *);
extern void ospf_check_abr_status(struct ospf *);
extern void ospf_abr_task(struct ospf *);
+extern void ospf_abr_nssa_task(struct ospf *ospf);
extern void ospf_schedule_abr_task(struct ospf *);
extern void ospf_abr_announce_network_to_area(struct prefix_ipv4 *, uint32_t,
struct ospf_area *);
+extern void ospf_abr_nssa_type7_defaults(struct ospf *ospf);
extern void ospf_abr_nssa_check_status(struct ospf *ospf);
extern void ospf_abr_generate_indication_lsa(struct ospf *ospf,
const struct ospf_area *area);
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 649ba70e02..5742ece1f7 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -651,6 +651,8 @@ int ospf_if_new_hook(struct interface *ifp)
ifp->info = XCALLOC(MTYPE_OSPF_IF_INFO, sizeof(struct ospf_if_info));
+ IF_OSPF_IF_INFO(ifp)->oii_fd = -1;
+
IF_OIFS(ifp) = route_table_init();
IF_OIFS_PARAMS(ifp) = route_table_init();
@@ -691,6 +693,8 @@ static int ospf_if_delete_hook(struct interface *ifp)
{
int rc = 0;
struct route_node *rn;
+ struct ospf_if_info *oii;
+
rc = ospf_opaque_del_if(ifp);
/*
@@ -707,6 +711,13 @@ static int ospf_if_delete_hook(struct interface *ifp)
route_table_finish(IF_OIFS(ifp));
route_table_finish(IF_OIFS_PARAMS(ifp));
+ /* Close per-interface socket */
+ oii = ifp->info;
+ if (oii && oii->oii_fd > 0) {
+ close(oii->oii_fd);
+ oii->oii_fd = -1;
+ }
+
XFREE(MTYPE_OSPF_IF_INFO, ifp->info);
return rc;
@@ -1367,6 +1378,16 @@ static int ospf_ifp_up(struct interface *ifp)
struct ospf_interface *oi;
struct route_node *rn;
struct ospf_if_info *oii = ifp->info;
+ struct ospf *ospf;
+
+ if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
+ zlog_debug("Zebra: Interface[%s] state change to up.",
+ ifp->name);
+
+ /* Open per-intf write socket if configured */
+ ospf = ifp->vrf->info;
+ if (ospf && ospf->intf_socket_enabled)
+ ospf_ifp_sock_init(ifp);
ospf_if_recalculate_output_cost(ifp);
@@ -1384,10 +1405,6 @@ static int ospf_ifp_up(struct interface *ifp)
return 0;
}
- if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
- zlog_debug("Zebra: Interface[%s] state change to up.",
- ifp->name);
-
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
if ((oi = rn->info) == NULL)
continue;
@@ -1416,6 +1433,9 @@ static int ospf_ifp_down(struct interface *ifp)
ospf_if_down(oi);
}
+ /* Close per-interface write socket if configured */
+ ospf_ifp_sock_close(ifp);
+
return 0;
}
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index 8625a72ac1..649df437a4 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -121,6 +121,9 @@ struct ospf_if_info {
membership_counts[MEMBER_MAX]; /* multicast group refcnts */
uint32_t curr_mtu;
+
+ /* Per-interface write socket, configured via 'ospf' object */
+ int oii_fd;
};
struct ospf_interface;
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 82f7b96fd5..9e2dd7a457 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -1654,9 +1654,6 @@ struct in_addr ospf_get_nssa_ip(struct ospf_area *area)
if (best_default.s_addr != INADDR_ANY)
return best_default;
- if (best_default.s_addr != INADDR_ANY)
- return best_default;
-
return fwd;
}
@@ -1868,8 +1865,7 @@ static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf,
}
/* As Type-7 */
-static void ospf_install_flood_nssa(struct ospf *ospf, struct ospf_lsa *lsa,
- struct external_info *ei)
+static void ospf_install_flood_nssa(struct ospf *ospf, struct ospf_lsa *lsa)
{
struct ospf_lsa *new;
struct as_external_lsa *extlsa;
@@ -2017,7 +2013,7 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf,
struct ospf_lsa *type7,
struct ospf_lsa *type5)
{
- struct ospf_lsa *new;
+ struct ospf_lsa *new, *translated_lsa;
struct as_external_lsa *extnew;
if (ospf->gr_info.restart_in_progress) {
@@ -2031,7 +2027,8 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf,
* the OSPF_LSA_LOCAL_XLT flag, must originate by hand
*/
- if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) {
+ if ((translated_lsa = ospf_lsa_translated_nssa_new(ospf, type7)) ==
+ NULL) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
"%s: Could not translate Type-7, Id %pI4, to Type-5",
@@ -2039,16 +2036,17 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf,
return NULL;
}
- extnew = (struct as_external_lsa *)new->data;
+ extnew = (struct as_external_lsa *)translated_lsa->data;
/* Update LSA sequence number from translated Type-5 LSA */
if (type5)
- new->data->ls_seqnum = lsa_seqnum_increment(type5);
+ translated_lsa->data->ls_seqnum = lsa_seqnum_increment(type5);
- if ((new = ospf_lsa_install(ospf, NULL, new)) == NULL) {
+ if ((new = ospf_lsa_install(ospf, NULL, translated_lsa)) == NULL) {
flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
"%s: Could not install LSA id %pI4", __func__,
&type7->data->id);
+ ospf_lsa_free(translated_lsa);
return NULL;
}
@@ -2071,7 +2069,7 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
struct ospf_lsa *type7,
struct ospf_lsa *type5)
{
- struct ospf_lsa *new = NULL;
+ struct ospf_lsa *new = NULL, *translated_lsa = NULL;
struct as_external_lsa *extold = NULL;
uint32_t ls_seqnum = 0;
@@ -2147,7 +2145,8 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
ospf_ls_retransmit_delete_nbr_as(ospf, type5);
/* create new translated LSA */
- if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) {
+ if ((translated_lsa = ospf_lsa_translated_nssa_new(ospf, type7)) ==
+ NULL) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
"%s: Could not translate Type-7 for %pI4 to Type-5",
@@ -2157,13 +2156,14 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
if (type7->area->suppress_fa == 1) {
if (extold->e[0].fwd_addr.s_addr == 0)
- new->data->ls_seqnum = htonl(ls_seqnum + 1);
+ translated_lsa->data->ls_seqnum = htonl(ls_seqnum + 1);
}
- if (!(new = ospf_lsa_install(ospf, NULL, new))) {
+ if (!(new = ospf_lsa_install(ospf, NULL, translated_lsa))) {
flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
"%s: Could not install translated LSA, Id %pI4",
__func__, &type7->data->id);
+ ospf_lsa_free(translated_lsa);
return NULL;
}
@@ -2253,7 +2253,7 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
/* stay away from translated LSAs! */
!(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)))
ospf_install_flood_nssa(
- ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */
+ ospf, new); /* Install/Flood Type-7 to all NSSAs */
/* Debug logging. */
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
@@ -2266,6 +2266,100 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
return new;
}
+/* Originate an NSSA-LSA, install and flood. */
+struct ospf_lsa *ospf_nssa_lsa_originate(struct ospf_area *area,
+ struct external_info *ei)
+{
+ struct ospf *ospf = area->ospf;
+ struct ospf_lsa *new;
+
+ if (ospf->gr_info.restart_in_progress) {
+ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
+ zlog_debug(
+ "LSA[Type7]: Graceful Restart in progress, don't originate");
+ return NULL;
+ }
+
+ if (ospf->router_id.s_addr == INADDR_ANY) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "LSA[Type7:%pI4]: deferring NSSA-LSA origination, router ID is zero",
+ &ei->p.prefix);
+ return NULL;
+ }
+
+ /* Create new NSSA-LSA instance. */
+ if ((new = ospf_external_lsa_new(ospf, ei, NULL)) == NULL) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "LSA[Type7:%pI4]: Could not originate NSSA-LSA",
+ &ei->p.prefix);
+ return NULL;
+ }
+ new->data->type = OSPF_AS_NSSA_LSA;
+ new->area = area;
+
+ /* Install newly created LSA into Type-7 LSDB. */
+ ospf_lsa_install(ospf, NULL, new);
+
+ /* Update LSA origination count. */
+ ospf->lsa_originate_count++;
+
+ /* Flooding new LSA */
+ ospf_flood_through_area(area, NULL, new);
+
+ /* Debug logging. */
+ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
+ zlog_debug("LSA[Type%d:%pI4]: Originate NSSA-LSA %p",
+ new->data->type, &new->data->id, (void *)new);
+ ospf_lsa_header_dump(new->data);
+ }
+
+ return new;
+}
+
+/* Refresh NSSA-LSA. */
+struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area,
+ struct ospf_lsa *lsa,
+ struct external_info *ei)
+{
+ struct ospf *ospf = area->ospf;
+ struct ospf_lsa *new;
+
+ /* Delete LSA from neighbor retransmit-list. */
+ ospf_ls_retransmit_delete_nbr_as(ospf, lsa);
+
+ /* Unregister AS-external-LSA from refresh-list. */
+ ospf_refresher_unregister_lsa(ospf, lsa);
+
+ /* Create new NSSA-LSA instance. */
+ if ((new = ospf_external_lsa_new(ospf, ei, NULL)) == NULL) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "LSA[Type7:%pI4]: Could not originate NSSA-LSA",
+ &ei->p.prefix);
+ return NULL;
+ }
+ new->data->type = OSPF_AS_NSSA_LSA;
+ new->data->ls_seqnum = lsa_seqnum_increment(lsa);
+ new->area = area;
+
+ /* Install newly created LSA into Type-7 LSDB. */
+ ospf_lsa_install(ospf, NULL, new);
+
+ /* Flooding new LSA */
+ ospf_flood_through_area(area, NULL, new);
+
+ /* Debug logging. */
+ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
+ zlog_debug("LSA[Type%d:%pI4]: NSSA-LSA refresh",
+ new->data->type, &new->data->id);
+ ospf_lsa_header_dump(new->data);
+ }
+
+ return new;
+}
+
static struct external_info *ospf_default_external_info(struct ospf *ospf)
{
int type;
@@ -2611,8 +2705,8 @@ struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *ospf,
/* If any attached NSSA, install as Type-7, flood to all NSSA Areas */
if (ospf->anyNSSA && !(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)))
- ospf_install_flood_nssa(ospf, new,
- ei); /* Install/Flood per new rules */
+ ospf_install_flood_nssa(ospf,
+ new); /* Install/Flood per new rules */
/* Register self-originated LSA to refresh queue.
* Translated LSAs should not be registered, but refreshed upon
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index 8ab293f4db..d5ca0694cc 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -278,6 +278,11 @@ extern struct in_addr ospf_get_ip_from_ifp(struct ospf_interface *);
extern struct ospf_lsa *ospf_external_lsa_originate(struct ospf *,
struct external_info *);
+extern struct ospf_lsa *ospf_nssa_lsa_originate(struct ospf_area *area,
+ struct external_info *ei);
+extern struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area,
+ struct ospf_lsa *lsa,
+ struct external_info *ei);
extern void ospf_external_lsa_rid_change(struct ospf *ospf);
extern struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *,
uint32_t, struct in_addr,
diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c
index d3f30ce1ee..aff8ed05c7 100644
--- a/ospfd/ospf_network.c
+++ b/ospfd/ospf_network.c
@@ -15,6 +15,7 @@
#include "sockopt.h"
#include "privs.h"
#include "lib_errors.h"
+#include "lib/table.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_network.h"
@@ -111,7 +112,7 @@ int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p,
"can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %pI4, ifindex %u, AllDRouters): %s",
top->fd, &p->u.prefix4, ifindex,
safe_strerror(errno));
- else
+ else if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"interface %pI4 [%u] leave AllDRouters Multicast group.",
&p->u.prefix4, ifindex);
@@ -119,62 +120,60 @@ int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p,
return ret;
}
-int ospf_if_ipmulticast(struct ospf *top, struct prefix *p, ifindex_t ifindex)
+int ospf_if_ipmulticast(int fd, struct prefix *p, ifindex_t ifindex)
{
uint8_t val;
int ret, len;
/* Prevent receiving self-origined multicast packets. */
- ret = setsockopt_ipv4_multicast_loop(top->fd, 0);
+ ret = setsockopt_ipv4_multicast_loop(fd, 0);
if (ret < 0)
flog_err(EC_LIB_SOCKET,
"can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s",
- top->fd, safe_strerror(errno));
+ fd, safe_strerror(errno));
/* Explicitly set multicast ttl to 1 -- endo. */
val = 1;
len = sizeof(val);
- ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val,
- len);
+ ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len);
if (ret < 0)
flog_err(EC_LIB_SOCKET,
"can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",
- top->fd, safe_strerror(errno));
+ fd, safe_strerror(errno));
#ifndef GNU_LINUX
/* For GNU LINUX ospf_write uses IP_PKTINFO, in_pktinfo to send
* packet out of ifindex. Below would be used Non Linux system.
*/
- ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex);
+ ret = setsockopt_ipv4_multicast_if(fd, p->u.prefix4, ifindex);
if (ret < 0)
flog_err(EC_LIB_SOCKET,
"can't setsockopt IP_MULTICAST_IF(fd %d, addr %pI4, ifindex %u): %s",
- top->fd, &p->u.prefix4, ifindex,
+ fd, &p->u.prefix4, ifindex,
safe_strerror(errno));
#endif
return ret;
}
-int ospf_sock_init(struct ospf *ospf)
+/*
+ * Helper to open and set up a socket; returns the new fd on success,
+ * -1 on error.
+ */
+static int sock_init_common(vrf_id_t vrf_id, const char *name, int *pfd)
{
int ospf_sock;
int ret, hincl = 1;
- int bufsize = (8 * 1024 * 1024);
-
- /* silently ignore. already done */
- if (ospf->fd > 0)
- return -1;
- if (ospf->vrf_id == VRF_UNKNOWN) {
+ if (vrf_id == VRF_UNKNOWN) {
/* silently return since VRF is not ready */
return -1;
}
+
frr_with_privs(&ospfd_privs) {
ospf_sock = vrf_socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP,
- ospf->vrf_id, ospf->name);
+ vrf_id, name);
if (ospf_sock < 0) {
- flog_err(EC_LIB_SOCKET,
- "ospf_read_sock_init: socket: %s",
+ flog_err(EC_LIB_SOCKET, "%s: socket: %s", __func__,
safe_strerror(errno));
return -1;
}
@@ -213,9 +212,102 @@ int ospf_sock_init(struct ospf *ospf)
ospf_sock);
}
- setsockopt_so_sendbuf(ospf_sock, bufsize);
- setsockopt_so_recvbuf(ospf_sock, bufsize);
+ *pfd = ospf_sock;
- ospf->fd = ospf_sock;
return ret;
}
+
+/*
+ * Update a socket bufsize(s), based on its ospf instance
+ */
+void ospf_sock_bufsize_update(const struct ospf *ospf, int sock,
+ enum ospf_sock_type_e type)
+{
+ int bufsize;
+
+ if (type == OSPF_SOCK_BOTH || type == OSPF_SOCK_RECV) {
+ bufsize = ospf->recv_sock_bufsize;
+ setsockopt_so_recvbuf(sock, bufsize);
+ }
+
+ if (type == OSPF_SOCK_BOTH || type == OSPF_SOCK_SEND) {
+ bufsize = ospf->send_sock_bufsize;
+ setsockopt_so_sendbuf(sock, bufsize);
+ }
+}
+
+int ospf_sock_init(struct ospf *ospf)
+{
+ int ret;
+
+ /* silently ignore. already done */
+ if (ospf->fd > 0)
+ return -1;
+
+ ret = sock_init_common(ospf->vrf_id, ospf->name, &(ospf->fd));
+
+ if (ret >= 0) /* Update socket buffer sizes */
+ ospf_sock_bufsize_update(ospf, ospf->fd, OSPF_SOCK_BOTH);
+
+ return ret;
+}
+
+/*
+ * Open per-interface write socket
+ */
+int ospf_ifp_sock_init(struct interface *ifp)
+{
+ struct ospf_if_info *oii;
+ struct ospf_interface *oi;
+ struct ospf *ospf;
+ struct route_node *rn;
+ int ret;
+
+ oii = IF_OSPF_IF_INFO(ifp);
+ if (oii == NULL)
+ return -1;
+
+ if (oii->oii_fd > 0)
+ return 0;
+
+ rn = route_top(IF_OIFS(ifp));
+ if (rn && rn->info) {
+ oi = rn->info;
+ ospf = oi->ospf;
+ } else
+ return -1;
+
+ ret = sock_init_common(ifp->vrf->vrf_id, ifp->name, &oii->oii_fd);
+
+ if (ret >= 0) /* Update socket buffer sizes */
+ ospf_sock_bufsize_update(ospf, oii->oii_fd, OSPF_SOCK_BOTH);
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("%s: ifp %s, oii %p, fd %d", __func__, ifp->name,
+ oii, oii->oii_fd);
+
+ return ret;
+}
+
+/*
+ * Close per-interface write socket
+ */
+int ospf_ifp_sock_close(struct interface *ifp)
+{
+ struct ospf_if_info *oii;
+
+ oii = IF_OSPF_IF_INFO(ifp);
+ if (oii == NULL)
+ return 0;
+
+ if (oii->oii_fd > 0) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("%s: ifp %s, oii %p, fd %d", __func__,
+ ifp->name, oii, oii->oii_fd);
+
+ close(oii->oii_fd);
+ oii->oii_fd = -1;
+ }
+
+ return 0;
+}
diff --git a/ospfd/ospf_network.h b/ospfd/ospf_network.h
index 33fd8980bf..b810bad50b 100644
--- a/ospfd/ospf_network.h
+++ b/ospfd/ospf_network.h
@@ -13,7 +13,20 @@ extern int ospf_if_drop_allspfrouters(struct ospf *, struct prefix *,
ifindex_t);
extern int ospf_if_add_alldrouters(struct ospf *, struct prefix *, ifindex_t);
extern int ospf_if_drop_alldrouters(struct ospf *, struct prefix *, ifindex_t);
-extern int ospf_if_ipmulticast(struct ospf *, struct prefix *, ifindex_t);
+extern int ospf_if_ipmulticast(int fd, struct prefix *, ifindex_t);
extern int ospf_sock_init(struct ospf *ospf);
+/* Open, close per-interface write socket */
+int ospf_ifp_sock_init(struct interface *ifp);
+int ospf_ifp_sock_close(struct interface *ifp);
+
+enum ospf_sock_type_e {
+ OSPF_SOCK_NONE = 0,
+ OSPF_SOCK_RECV,
+ OSPF_SOCK_SEND,
+ OSPF_SOCK_BOTH
+};
+
+void ospf_sock_bufsize_update(const struct ospf *ospf, int sock,
+ enum ospf_sock_type_e type);
#endif /* _ZEBRA_OSPF_NETWORK_H */
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 5f7d49e0bb..552acfd6d3 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -618,7 +618,7 @@ static void ospf_write(struct event *thread)
struct msghdr msg;
struct iovec iov[2];
uint8_t type;
- int ret;
+ int ret, fd;
int flags = 0;
struct listnode *node;
#ifdef WANT_OSPF_WRITE_FRAGMENT
@@ -633,11 +633,12 @@ static void ospf_write(struct event *thread)
struct cmsghdr *cm = (struct cmsghdr *)cmsgbuf;
struct in_pktinfo *pi;
#endif
+ fd = ospf->fd;
- if (ospf->fd < 0 || ospf->oi_running == 0) {
+ if (fd < 0 || ospf->oi_running == 0) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s failed to send, fd %d, instance %u",
- __func__, ospf->fd, ospf->oi_running);
+ __func__, fd, ospf->oi_running);
return;
}
@@ -657,6 +658,15 @@ static void ospf_write(struct event *thread)
/* convenience - max OSPF data per packet */
maxdatasize = oi->ifp->mtu - sizeof(struct ip);
#endif /* WANT_OSPF_WRITE_FRAGMENT */
+
+ /* Reset socket fd to use. */
+ fd = ospf->fd;
+
+ /* Check for per-interface socket */
+ if (ospf->intf_socket_enabled &&
+ (IF_OSPF_IF_INFO(oi->ifp))->oii_fd > 0)
+ fd = (IF_OSPF_IF_INFO(oi->ifp))->oii_fd;
+
/* Get one packet from queue. */
op = ospf_fifo_head(oi->obuf);
assert(op);
@@ -664,8 +674,7 @@ static void ospf_write(struct event *thread)
if (op->dst.s_addr == htonl(OSPF_ALLSPFROUTERS)
|| op->dst.s_addr == htonl(OSPF_ALLDROUTERS))
- ospf_if_ipmulticast(ospf, oi->address,
- oi->ifp->ifindex);
+ ospf_if_ipmulticast(fd, oi->address, oi->ifp->ifindex);
/* Rewrite the md5 signature & update the seq */
ospf_make_md5_digest(oi, op);
@@ -760,13 +769,13 @@ static void ospf_write(struct event *thread)
#ifdef WANT_OSPF_WRITE_FRAGMENT
if (op->length > maxdatasize)
- ospf_write_frags(ospf->fd, op, &iph, &msg, maxdatasize,
+ ospf_write_frags(fd, op, &iph, &msg, maxdatasize,
oi->ifp->mtu, flags, type);
#endif /* WANT_OSPF_WRITE_FRAGMENT */
/* send final fragment (could be first) */
sockopt_iphdrincl_swab_htosys(&iph);
- ret = sendmsg(ospf->fd, &msg, flags);
+ ret = sendmsg(fd, &msg, flags);
sockopt_iphdrincl_swab_systoh(&iph);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c
index 5f18bff1cf..75868056ad 100644
--- a/ospfd/ospf_route.c
+++ b/ospfd/ospf_route.c
@@ -1008,7 +1008,8 @@ void ospf_prune_unreachable_routers(struct route_table *rtrs)
}
int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
- struct ospf_area *area, struct prefix_ipv4 *p)
+ struct ospf_area *area, struct prefix_ipv4 *p,
+ bool nssa)
{
struct route_node *rn;
struct ospf_route * or, *new_or;
@@ -1027,7 +1028,7 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
or = rn->info;
- if (or->path_type == OSPF_PATH_INTRA_AREA) {
+ if (!nssa && or->path_type == OSPF_PATH_INTRA_AREA) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: an intra-area route exists",
__func__);
@@ -1054,7 +1055,10 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
new_or->cost = 0;
new_or->u.std.area_id = area->area_id;
new_or->u.std.external_routing = area->external_routing;
- new_or->path_type = OSPF_PATH_INTER_AREA;
+ if (nssa)
+ new_or->path_type = OSPF_PATH_TYPE2_EXTERNAL;
+ else
+ new_or->path_type = OSPF_PATH_INTER_AREA;
rn->info = new_or;
ospf_zebra_add_discard(ospf, p);
@@ -1063,7 +1067,7 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
}
void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt,
- struct prefix_ipv4 *p)
+ struct prefix_ipv4 *p, bool nssa)
{
struct route_node *rn;
struct ospf_route * or ;
@@ -1081,7 +1085,7 @@ void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt,
or = rn->info;
- if (or->path_type == OSPF_PATH_INTRA_AREA) {
+ if (!nssa && or->path_type == OSPF_PATH_INTRA_AREA) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: an intra-area route exists", __func__);
return;
diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h
index 2582067aec..7639a0049e 100644
--- a/ospfd/ospf_route.h
+++ b/ospfd/ospf_route.h
@@ -152,9 +152,10 @@ extern void ospf_route_subst_nexthops(struct ospf_route *, struct list *);
extern void ospf_prune_unreachable_networks(struct route_table *);
extern void ospf_prune_unreachable_routers(struct route_table *);
extern int ospf_add_discard_route(struct ospf *, struct route_table *,
- struct ospf_area *, struct prefix_ipv4 *);
+ struct ospf_area *, struct prefix_ipv4 *,
+ bool);
extern void ospf_delete_discard_route(struct ospf *, struct route_table *,
- struct prefix_ipv4 *);
+ struct prefix_ipv4 *, bool);
extern int ospf_route_match_same(struct route_table *, struct prefix_ipv4 *,
struct ospf_route *);
diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c
index 3087008819..3d5c5aa2d5 100644
--- a/ospfd/ospf_routemap.c
+++ b/ospfd/ospf_routemap.c
@@ -120,7 +120,7 @@ route_match_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
alist = access_list_lookup(AFI_IP, (char *)rule);
if (alist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -168,7 +168,7 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
plist = prefix_list_lookup(AFI_IP, (char *)rule);
if (plist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -245,7 +245,7 @@ route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
alist = access_list_lookup(AFI_IP, (char *)rule);
if (alist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -286,7 +286,7 @@ route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
plist = prefix_list_lookup(AFI_IP, (char *)rule);
if (plist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c
index 2982cc7d6f..fcc43e7311 100644
--- a/ospfd/ospf_snmp.c
+++ b/ospfd/ospf_snmp.c
@@ -1112,7 +1112,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v,
oid2in_addr(offset, IN_ADDR_SIZE, range_net);
p.prefix = *range_net;
- return ospf_area_range_lookup(area, &p);
+ return ospf_area_range_lookup(area, area->ranges, &p);
} else {
/* Set OID offset for Area ID. */
offset = name + v->namelen;
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index dc9dd34303..b140027147 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -1781,7 +1781,7 @@ static void ospf_te_update_link(struct ls_ted *ted, struct ls_vertex *vertex,
* @param metric Standard metric attached to this Edge
*/
static void ospf_te_update_subnet(struct ls_ted *ted, struct ls_vertex *vertex,
- struct prefix p, uint8_t metric)
+ struct prefix *p, uint8_t metric)
{
struct ls_subnet *subnet;
struct ls_prefix *ls_pref;
@@ -1840,7 +1840,7 @@ static void ospf_te_delete_subnet(struct ls_ted *ted, struct in_addr addr)
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = addr;
- subnet = ls_find_subnet(ted, p);
+ subnet = ls_find_subnet(ted, &p);
/* Remove subnet if found */
if (subnet) {
@@ -1933,7 +1933,7 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = rl->link[i].link_data;
metric = ntohs(rl->link[i].metric);
- ospf_te_update_subnet(ted, vertex, p, metric);
+ ospf_te_update_subnet(ted, vertex, &p, metric);
break;
case LSA_LINK_TYPE_STUB:
/* Keep only /32 prefix */
@@ -1942,7 +1942,7 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
p.family = AF_INET;
p.u.prefix4 = rl->link[i].link_id;
metric = ntohs(rl->link[i].metric);
- ospf_te_update_subnet(ted, vertex, p, metric);
+ ospf_te_update_subnet(ted, vertex, &p, metric);
}
break;
default:
@@ -2074,12 +2074,12 @@ static void ospf_te_update_remote_asbr(struct ls_ted *ted, struct ls_edge *edge)
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = attr->standard.local;
- ospf_te_update_subnet(ted, edge->source, p, attr->standard.te_metric);
+ ospf_te_update_subnet(ted, edge->source, &p, attr->standard.te_metric);
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = attr->standard.remote_addr;
- ospf_te_update_subnet(ted, vertex, p, attr->standard.te_metric);
+ ospf_te_update_subnet(ted, vertex, &p, attr->standard.te_metric);
/* Connect Edge to the remote Vertex */
if (edge->destination == NULL) {
@@ -2625,14 +2625,14 @@ static int ospf_te_parse_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)
pref.family = AF_INET;
pref.prefixlen = ext->pref_length;
pref.u.prefix4 = ext->address;
- subnet = ls_find_subnet(ted, pref);
+ subnet = ls_find_subnet(ted, &pref);
/* Create new Link State Prefix if not found */
if (!subnet) {
lnid.origin = OSPFv2;
lnid.id.ip.addr = lsa->data->adv_router;
lnid.id.ip.area_id = lsa->area->area_id;
- ls_pref = ls_prefix_new(lnid, pref);
+ ls_pref = ls_prefix_new(lnid, &pref);
/* and add it to the TED */
subnet = ls_subnet_add(ted, ls_pref);
}
@@ -2698,7 +2698,7 @@ static int ospf_te_delete_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)
pref.family = AF_INET;
pref.prefixlen = ext->pref_length;
pref.u.prefix4 = ext->address;
- subnet = ls_find_subnet(ted, pref);
+ subnet = ls_find_subnet(ted, &pref);
/* Check if there is a corresponding subnet */
if (!subnet)
@@ -4398,7 +4398,7 @@ DEFUN (show_ip_ospf_mpls_te_db,
return CMD_WARNING_CONFIG_FAILED;
}
/* Get the Subnet from the Link State Database */
- subnet = ls_find_subnet(OspfMplsTE.ted, pref);
+ subnet = ls_find_subnet(OspfMplsTE.ted, &pref);
if (!subnet) {
vty_out(vty, "No subnet found for ID %pFX\n",
&pref);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 8c0afd8527..3c0e0fcb63 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -35,12 +35,11 @@
#include "ospfd/ospf_spf.h"
#include "ospfd/ospf_route.h"
#include "ospfd/ospf_zebra.h"
-/*#include "ospfd/ospf_routemap.h" */
#include "ospfd/ospf_vty.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_bfd.h"
#include "ospfd/ospf_ldp_sync.h"
-
+#include "ospfd/ospf_network.h"
FRR_CFG_DEFAULT_BOOL(OSPF_LOG_ADJACENCY_CHANGES,
{ .val_bool = true, .match_profile = "datacenter", },
@@ -611,6 +610,7 @@ DEFUN (ospf_area_range,
"Advertised metric for this range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ struct ospf_area *area;
int idx_ipv4_number = 1;
int idx_ipv4_prefixlen = 3;
int idx_cost = 6;
@@ -622,12 +622,14 @@ DEFUN (ospf_area_range,
VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg);
str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
- ospf_area_range_set(ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE);
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
+
+ ospf_area_range_set(ospf, area, area->ranges, &p,
+ OSPF_AREA_RANGE_ADVERTISE, false);
if (argc > 5) {
cost = strtoul(argv[idx_cost]->arg, NULL, 10);
- ospf_area_range_cost_set(ospf, area_id, &p, cost);
+ ospf_area_range_cost_set(ospf, area, area->ranges, &p, cost);
}
return CMD_SUCCESS;
@@ -647,6 +649,7 @@ DEFUN (ospf_area_range_cost,
"Network prefix to be announced instead of range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ struct ospf_area *area;
int idx_ipv4_number = 1;
int idx_ipv4_prefixlen = 3;
int idx = 4;
@@ -658,19 +661,20 @@ DEFUN (ospf_area_range_cost,
VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg);
str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
- ospf_area_range_set(ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE);
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
+ ospf_area_range_set(ospf, area, area->ranges, &p,
+ OSPF_AREA_RANGE_ADVERTISE, false);
if (argv_find(argv, argc, "cost", &idx)) {
cost = strtoul(argv[idx + 1]->arg, NULL, 10);
- ospf_area_range_cost_set(ospf, area_id, &p, cost);
+ ospf_area_range_cost_set(ospf, area, area->ranges, &p, cost);
}
idx = 4;
if (argv_find(argv, argc, "substitute", &idx)) {
str2prefix_ipv4(argv[idx + 1]->arg, &s);
- ospf_area_range_substitute_set(ospf, area_id, &p, &s);
+ ospf_area_range_substitute_set(ospf, area, &p, &s);
}
return CMD_SUCCESS;
@@ -687,6 +691,7 @@ DEFUN (ospf_area_range_not_advertise,
"DoNotAdvertise this range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ struct ospf_area *area;
int idx_ipv4_number = 1;
int idx_ipv4_prefixlen = 3;
struct prefix_ipv4 p;
@@ -696,10 +701,11 @@ DEFUN (ospf_area_range_not_advertise,
VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg);
str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
- ospf_area_range_set(ospf, area_id, &p, 0);
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
- ospf_area_range_substitute_unset(ospf, area_id, &p);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
+
+ ospf_area_range_set(ospf, area, area->ranges, &p, 0, false);
+ ospf_area_range_substitute_unset(ospf, area, &p);
return CMD_SUCCESS;
}
@@ -721,6 +727,7 @@ DEFUN (no_ospf_area_range,
"DoNotAdvertise this range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ struct ospf_area *area;
int idx_ipv4_number = 2;
int idx_ipv4_prefixlen = 4;
struct prefix_ipv4 p;
@@ -730,7 +737,10 @@ DEFUN (no_ospf_area_range,
VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg);
str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
- ospf_area_range_unset(ospf, area_id, &p);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
+
+ ospf_area_range_unset(ospf, area, area->ranges, &p);
return CMD_SUCCESS;
}
@@ -748,6 +758,7 @@ DEFUN (no_ospf_area_range_substitute,
"Network prefix to be announced instead of range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ struct ospf_area *area;
int idx_ipv4_number = 2;
int idx_ipv4_prefixlen = 4;
int idx_ipv4_prefixlen_2 = 6;
@@ -759,7 +770,10 @@ DEFUN (no_ospf_area_range_substitute,
str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
str2prefix_ipv4(argv[idx_ipv4_prefixlen_2]->arg, &s);
- ospf_area_range_substitute_unset(ospf, area_id, &p);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
+
+ ospf_area_range_substitute_unset(ospf, area, &p);
return CMD_SUCCESS;
}
@@ -1433,15 +1447,35 @@ DEFUN (no_ospf_area_stub_no_summary,
return CMD_SUCCESS;
}
-static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc,
- struct cmd_token **argv, int cfg_nosum,
- int nosum)
+DEFPY (ospf_area_nssa,
+ ospf_area_nssa_cmd,
+ "area <A.B.C.D|(0-4294967295)>$area_str nssa\
+ [{\
+ <translate-candidate|translate-never|translate-always>$translator_role\
+ |default-information-originate$dflt_originate [{metric (0-16777214)$mval|metric-type (1-2)$mtype}]\
+ |no-summary$no_summary\
+ |suppress-fa$suppress_fa\
+ }]",
+ "OSPF area parameters\n"
+ "OSPF area ID in IP address format\n"
+ "OSPF area ID as a decimal value\n"
+ "Configure OSPF area as nssa\n"
+ "Configure NSSA-ABR for translate election (default)\n"
+ "Configure NSSA-ABR to never translate\n"
+ "Configure NSSA-ABR to always translate\n"
+ "Originate Type 7 default into NSSA area\n"
+ "OSPF default metric\n"
+ "OSPF metric\n"
+ "OSPF metric type for default routes\n"
+ "Set OSPF External Type 1/2 metrics\n"
+ "Do not inject inter-area routes into nssa\n"
+ "Suppress forwarding address\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct in_addr area_id;
int ret, format;
- VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, argv[1]->arg);
+ VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, area_str);
ret = ospf_area_nssa_set(ospf, area_id);
ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
@@ -1452,14 +1486,14 @@ static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc,
return CMD_WARNING_CONFIG_FAILED;
}
- if (argc > 3) {
- if (strncmp(argv[3]->text, "translate-c", 11) == 0)
+ if (translator_role) {
+ if (strncmp(translator_role, "translate-c", 11) == 0)
ospf_area_nssa_translator_role_set(
ospf, area_id, OSPF_NSSA_ROLE_CANDIDATE);
- else if (strncmp(argv[3]->text, "translate-n", 11) == 0)
+ else if (strncmp(translator_role, "translate-n", 11) == 0)
ospf_area_nssa_translator_role_set(
ospf, area_id, OSPF_NSSA_ROLE_NEVER);
- else if (strncmp(argv[3]->text, "translate-a", 11) == 0)
+ else if (strncmp(translator_role, "translate-a", 11) == 0)
ospf_area_nssa_translator_role_set(
ospf, area_id, OSPF_NSSA_ROLE_ALWAYS);
} else {
@@ -1467,12 +1501,27 @@ static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc,
OSPF_NSSA_ROLE_CANDIDATE);
}
- if (cfg_nosum) {
- if (nosum)
- ospf_area_no_summary_set(ospf, area_id);
- else
- ospf_area_no_summary_unset(ospf, area_id);
- }
+ if (dflt_originate) {
+ int metric_type = DEFAULT_METRIC_TYPE;
+
+ if (mval_str == NULL)
+ mval = -1;
+ if (mtype_str)
+ (void)str2metric_type(mtype_str, &metric_type);
+ ospf_area_nssa_default_originate_set(ospf, area_id, mval,
+ metric_type);
+ } else
+ ospf_area_nssa_default_originate_unset(ospf, area_id);
+
+ if (no_summary)
+ ospf_area_nssa_no_summary_set(ospf, area_id);
+ else
+ ospf_area_no_summary_unset(ospf, area_id);
+
+ if (suppress_fa)
+ ospf_area_nssa_suppress_fa_set(ospf, area_id);
+ else
+ ospf_area_nssa_suppress_fa_unset(ospf, area_id);
/* Flush the external LSA for the specified area */
ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_EXTERNAL_LSA);
@@ -1482,168 +1531,125 @@ static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc,
return CMD_SUCCESS;
}
-
-DEFUN (ospf_area_nssa_translate,
- ospf_area_nssa_translate_cmd,
- "area <A.B.C.D|(0-4294967295)> nssa <translate-candidate|translate-never|translate-always>",
+DEFPY (no_ospf_area_nssa,
+ no_ospf_area_nssa_cmd,
+ "no area <A.B.C.D|(0-4294967295)>$area_str nssa\
+ [{\
+ <translate-candidate|translate-never|translate-always>\
+ |default-information-originate [{metric (0-16777214)|metric-type (1-2)}]\
+ |no-summary\
+ |suppress-fa\
+ }]",
+ NO_STR
"OSPF area parameters\n"
"OSPF area ID in IP address format\n"
"OSPF area ID as a decimal value\n"
"Configure OSPF area as nssa\n"
"Configure NSSA-ABR for translate election (default)\n"
"Configure NSSA-ABR to never translate\n"
- "Configure NSSA-ABR to always translate\n")
-{
- return ospf_area_nssa_cmd_handler(vty, argc, argv, 0, 0);
-}
-
-DEFUN (ospf_area_nssa,
- ospf_area_nssa_cmd,
- "area <A.B.C.D|(0-4294967295)> nssa",
- "OSPF area parameters\n"
- "OSPF area ID in IP address format\n"
- "OSPF area ID as a decimal value\n"
- "Configure OSPF area as nssa\n")
-{
- return ospf_area_nssa_cmd_handler(vty, argc, argv, 0, 0);
-}
-
-DEFUN(ospf_area_nssa_suppress_fa, ospf_area_nssa_suppress_fa_cmd,
- "area <A.B.C.D|(0-4294967295)> nssa suppress-fa",
- "OSPF area parameters\n"
- "OSPF area ID in IP address format\n"
- "OSPF area ID as a decimal value\n"
- "Configure OSPF area as nssa\n"
- "Suppress forwarding address\n")
+ "Configure NSSA-ABR to always translate\n"
+ "Originate Type 7 default into NSSA area\n"
+ "OSPF default metric\n"
+ "OSPF metric\n"
+ "OSPF metric type for default routes\n"
+ "Set OSPF External Type 1/2 metrics\n"
+ "Do not inject inter-area routes into nssa\n"
+ "Suppress forwarding address\n")
{
- int idx_ipv4_number = 1;
- struct in_addr area_id;
- int format;
-
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format,
- argv[idx_ipv4_number]->arg);
-
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
- ospf_area_nssa_suppress_fa_set(ospf, area_id);
-
- ospf_schedule_abr_task(ospf);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(no_ospf_area_nssa_suppress_fa, no_ospf_area_nssa_suppress_fa_cmd,
- "no area <A.B.C.D|(0-4294967295)> nssa suppress-fa",
- NO_STR
- "OSPF area parameters\n"
- "OSPF area ID in IP address format\n"
- "OSPF area ID as a decimal value\n"
- "Configure OSPF area as nssa\n"
- "Suppress forwarding address\n")
-{
- int idx_ipv4_number = 2;
struct in_addr area_id;
int format;
- VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
-
- VTY_GET_OSPF_AREA_ID_NO_BB("nssa", area_id, format,
- argv[idx_ipv4_number]->arg);
+ VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, area_str);
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
+ /* Flush the NSSA LSA for the specified area */
+ ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_NSSA_LSA);
+ ospf_area_no_summary_unset(ospf, area_id);
+ ospf_area_nssa_default_originate_unset(ospf, area_id);
ospf_area_nssa_suppress_fa_unset(ospf, area_id);
+ ospf_area_nssa_unset(ospf, area_id);
ospf_schedule_abr_task(ospf);
return CMD_SUCCESS;
}
-DEFUN (ospf_area_nssa_no_summary,
- ospf_area_nssa_no_summary_cmd,
- "area <A.B.C.D|(0-4294967295)> nssa no-summary",
+DEFPY (ospf_area_nssa_range,
+ ospf_area_nssa_range_cmd,
+ "area <A.B.C.D|(0-4294967295)>$area_str nssa range A.B.C.D/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]",
"OSPF area parameters\n"
"OSPF area ID in IP address format\n"
"OSPF area ID as a decimal value\n"
"Configure OSPF area as nssa\n"
- "Do not inject inter-area routes into nssa\n")
+ "Configured address range\n"
+ "Specify IPv4 prefix\n"
+ "Do not advertise\n"
+ "User specified metric for this range\n"
+ "Advertised metric for this range\n")
{
- int idx_ipv4_number = 1;
- struct in_addr area_id;
- int format;
-
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format,
- argv[idx_ipv4_number]->arg);
-
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
- ospf_area_nssa_no_summary_set(ospf, area_id);
-
- ospf_schedule_abr_task(ospf);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ospf_area_nssa_no_summary,
- no_ospf_area_nssa_no_summary_cmd,
- "no area <A.B.C.D|(0-4294967295)> nssa no-summary",
- NO_STR
- "OSPF area parameters\n"
- "OSPF area ID in IP address format\n"
- "OSPF area ID as a decimal value\n"
- "Configure OSPF area as nssa\n"
- "Do not inject inter-area routes into nssa\n")
-{
- int idx_ipv4_number = 2;
+ struct ospf_area *area;
struct in_addr area_id;
int format;
+ int advertise = 0;
- VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ VTY_GET_OSPF_AREA_ID(area_id, format, area_str);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
- VTY_GET_OSPF_AREA_ID_NO_BB("nssa", area_id, format,
- argv[idx_ipv4_number]->arg);
+ if (area->external_routing != OSPF_AREA_NSSA) {
+ vty_out(vty, "%% First configure %s as an NSSA area\n",
+ area_str);
+ return CMD_WARNING;
+ }
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
- ospf_area_no_summary_unset(ospf, area_id);
+ if (!not_adv)
+ advertise = OSPF_AREA_RANGE_ADVERTISE;
- ospf_schedule_abr_task(ospf);
+ ospf_area_range_set(ospf, area, area->nssa_ranges,
+ (struct prefix_ipv4 *)prefix, advertise, true);
+ if (cost_str)
+ ospf_area_range_cost_set(ospf, area, area->nssa_ranges,
+ (struct prefix_ipv4 *)prefix, cost);
return CMD_SUCCESS;
}
-DEFUN (no_ospf_area_nssa,
- no_ospf_area_nssa_cmd,
- "no area <A.B.C.D|(0-4294967295)> nssa [<translate-candidate|translate-never|translate-always>]",
+DEFPY (no_ospf_area_nssa_range,
+ no_ospf_area_nssa_range_cmd,
+ "no area <A.B.C.D|(0-4294967295)>$area_str nssa range A.B.C.D/M$prefix [<not-advertise|cost (0-16777215)>]",
NO_STR
"OSPF area parameters\n"
"OSPF area ID in IP address format\n"
"OSPF area ID as a decimal value\n"
"Configure OSPF area as nssa\n"
- "Configure NSSA-ABR for translate election (default)\n"
- "Configure NSSA-ABR to never translate\n"
- "Configure NSSA-ABR to always translate\n")
+ "Configured address range\n"
+ "Specify IPv4 prefix\n"
+ "Do not advertise\n"
+ "User specified metric for this range\n"
+ "Advertised metric for this range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- int idx_ipv4_number = 2;
+ struct ospf_area *area;
struct in_addr area_id;
int format;
- VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format,
- argv[idx_ipv4_number]->arg);
+ VTY_GET_OSPF_AREA_ID(area_id, format, area_str);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
- /* Flush the NSSA LSA for the specified area */
- ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_NSSA_LSA);
- ospf_area_nssa_unset(ospf, area_id, argc);
+ if (area->external_routing != OSPF_AREA_NSSA) {
+ vty_out(vty, "%% First configure %s as an NSSA area\n",
+ area_str);
+ return CMD_WARNING;
+ }
- ospf_schedule_abr_task(ospf);
+ ospf_area_range_unset(ospf, area, area->nssa_ranges,
+ (struct prefix_ipv4 *)prefix);
return CMD_SUCCESS;
}
-
DEFUN (ospf_area_default_cost,
ospf_area_default_cost_cmd,
"area <A.B.C.D|(0-4294967295)> default-cost (0-16777215)",
@@ -3396,6 +3402,23 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf,
/* show LDP-Sync status */
ospf_ldp_sync_show_info(vty, ospf, json_vrf, json ? 1 : 0);
+ /* Socket buffer sizes */
+ if (json) {
+ if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+ json_object_int_add(json_vrf, "recvSockBufsize",
+ ospf->recv_sock_bufsize);
+ if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+ json_object_int_add(json_vrf, "sendSockBufsize",
+ ospf->send_sock_bufsize);
+ } else {
+ if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+ vty_out(vty, " Receive socket bufsize: %u\n",
+ ospf->recv_sock_bufsize);
+ if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+ vty_out(vty, " Send socket bufsize: %u\n",
+ ospf->send_sock_bufsize);
+ }
+
/* Show each area status. */
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
show_ip_ospf_area(vty, area, json_areas, json ? 1 : 0);
@@ -5065,6 +5088,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
json_object *json_neigh = NULL, *json_neigh_array = NULL;
char neigh_str[INET_ADDRSTRLEN] = {0};
char neigh_state[16] = {0};
+ struct ospf_neighbor *nbr_dr, *nbr_bdr;
if (use_json) {
if (prev_nbr &&
@@ -5192,19 +5216,38 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
}
}
- /* Show Designated Rotuer ID. */
- if (use_json)
- json_object_string_addf(json_neigh, "routerDesignatedId",
- "%pI4", &nbr->d_router);
- else
- vty_out(vty, " DR is %pI4,", &nbr->d_router);
+ /* Show Designated Router ID. */
+ if (DR(oi).s_addr == INADDR_ANY) {
+ if (!use_json)
+ vty_out(vty,
+ " No designated router on this network\n");
+ } else {
+ nbr_dr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi));
+ if (nbr_dr) {
+ if (use_json)
+ json_object_string_addf(
+ json_neigh, "routerDesignatedId",
+ "%pI4", &nbr_dr->router_id);
+ else
+ vty_out(vty, " DR is %pI4,",
+ &nbr_dr->router_id);
+ }
+ }
- /* Show Backup Designated Rotuer ID. */
- if (use_json)
- json_object_string_addf(json_neigh, "routerDesignatedBackupId",
- "%pI4", &nbr->bd_router);
- else
- vty_out(vty, " BDR is %pI4\n", &nbr->bd_router);
+ /* Show Backup Designated Router ID. */
+ nbr_bdr = ospf_nbr_lookup_by_addr(oi->nbrs, &BDR(oi));
+ if (nbr_bdr == NULL) {
+ if (!use_json)
+ vty_out(vty,
+ " No backup designated router on this network\n");
+ } else {
+ if (use_json)
+ json_object_string_addf(json_neigh,
+ "routerDesignatedBackupId",
+ "%pI4", &nbr_bdr->router_id);
+ else
+ vty_out(vty, " BDR is %pI4\n", &nbr_bdr->router_id);
+ }
/* Show options. */
if (use_json) {
@@ -11981,29 +12024,62 @@ static int config_write_ospf_area(struct vty *vty, struct ospf *ospf)
vty_out(vty, " no-summary\n");
vty_out(vty, "\n");
} else if (area->external_routing == OSPF_AREA_NSSA) {
+ vty_out(vty, " area %s nssa", buf);
+
switch (area->NSSATranslatorRole) {
case OSPF_NSSA_ROLE_NEVER:
- vty_out(vty,
- " area %s nssa translate-never\n",
- buf);
+ vty_out(vty, " translate-never");
break;
case OSPF_NSSA_ROLE_ALWAYS:
- vty_out(vty,
- " area %s nssa translate-always\n",
- buf);
+ vty_out(vty, " translate-always");
break;
case OSPF_NSSA_ROLE_CANDIDATE:
- vty_out(vty, " area %s nssa \n", buf);
break;
}
- if (area->no_summary)
+
+ if (area->nssa_default_originate.enabled) {
vty_out(vty,
- " area %s nssa no-summary\n",
- buf);
+ " default-information-originate");
+ if (area->nssa_default_originate
+ .metric_value != -1)
+ vty_out(vty, " metric %d",
+ area->nssa_default_originate
+ .metric_value);
+ if (area->nssa_default_originate
+ .metric_type !=
+ DEFAULT_METRIC_TYPE)
+ vty_out(vty, " metric-type 1");
+ }
+
+ if (area->no_summary)
+ vty_out(vty, " no-summary");
if (area->suppress_fa)
- vty_out(vty,
- " area %s nssa suppress-fa\n",
- buf);
+ vty_out(vty, " suppress-fa");
+ vty_out(vty, "\n");
+
+ for (rn1 = route_top(area->nssa_ranges); rn1;
+ rn1 = route_next(rn1)) {
+ struct ospf_area_range *range;
+
+ range = rn1->info;
+ if (!range)
+ continue;
+
+ vty_out(vty, " area %s nssa range %pFX",
+ buf, &rn1->p);
+
+ if (range->cost_config !=
+ OSPF_AREA_RANGE_COST_UNSPEC)
+ vty_out(vty, " cost %u",
+ range->cost_config);
+
+ if (!CHECK_FLAG(
+ range->flags,
+ OSPF_AREA_RANGE_ADVERTISE))
+ vty_out(vty, " not-advertise");
+
+ vty_out(vty, "\n");
+ }
}
if (area->default_cost != 1)
@@ -12434,6 +12510,9 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf)
if (ospf->fr_configured)
vty_out(vty, " flood-reduction\n");
+ if (!ospf->intf_socket_enabled)
+ vty_out(vty, " no socket-per-interface\n");
+
/* Redistribute information print. */
config_write_ospf_redistribute(vty, ospf);
@@ -12490,6 +12569,22 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf)
/* LDP-Sync print */
ospf_ldp_sync_write_config(vty, ospf);
+ /* Socket buffer sizes */
+ if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) {
+ if (ospf->send_sock_bufsize == ospf->recv_sock_bufsize)
+ vty_out(vty, " socket buffer all %u\n",
+ ospf->recv_sock_bufsize);
+ else
+ vty_out(vty, " socket buffer recv %u\n",
+ ospf->recv_sock_bufsize);
+ }
+
+ if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE &&
+ ospf->send_sock_bufsize != ospf->recv_sock_bufsize)
+ vty_out(vty, " socket buffer send %u\n",
+ ospf->send_sock_bufsize);
+
+
vty_out(vty, "exit\n");
write++;
@@ -12946,6 +13041,71 @@ DEFPY(no_flood_reduction_area, no_flood_reduction_area_cmd,
return CMD_SUCCESS;
}
+DEFPY(ospf_socket_bufsizes,
+ ospf_socket_bufsizes_cmd,
+ "[no] socket buffer <send$send_val | recv$recv_val | all$all_val> \
+ ![(1-4000000000)$bufsize]",
+ NO_STR
+ "Socket parameters\n"
+ "Buffer size configuration\n"
+ "Send buffer size\n"
+ "Receive buffer size\n"
+ "Both send and receive buffer sizes\n"
+ "Buffer size, in bytes\n")
+{
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ uint32_t recvsz, sendsz;
+
+ if (no)
+ bufsize = OSPF_DEFAULT_SOCK_BUFSIZE;
+
+ if (all_val) {
+ recvsz = bufsize;
+ sendsz = bufsize;
+ } else if (send_val) {
+ sendsz = bufsize;
+ recvsz = ospf->recv_sock_bufsize;
+ } else if (recv_val) {
+ recvsz = bufsize;
+ sendsz = ospf->send_sock_bufsize;
+ } else
+ return CMD_SUCCESS;
+
+ /* React to a change by modifying existing sockets */
+ ospf_update_bufsize(ospf, recvsz, sendsz);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (per_intf_socket,
+ per_intf_socket_cmd,
+ "[no] socket-per-interface",
+ NO_STR
+ "Use write socket per interface\n")
+{
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ struct listnode *node;
+ struct ospf_interface *oi;
+
+ if (no) {
+ if (ospf->intf_socket_enabled) {
+ ospf->intf_socket_enabled = false;
+
+ /* Iterate and close any sockets */
+ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi))
+ ospf_ifp_sock_close(oi->ifp);
+ }
+ } else if (!ospf->intf_socket_enabled) {
+ ospf->intf_socket_enabled = true;
+
+ /* Iterate and open sockets */
+ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi))
+ ospf_ifp_sock_init(oi->ifp);
+ }
+
+ return CMD_SUCCESS;
+}
+
void ospf_vty_clear_init(void)
{
install_element(ENABLE_NODE, &clear_ip_ospf_interface_cmd);
@@ -13029,12 +13189,9 @@ void ospf_vty_init(void)
/* "area nssa" commands. */
install_element(OSPF_NODE, &ospf_area_nssa_cmd);
- install_element(OSPF_NODE, &ospf_area_nssa_translate_cmd);
- install_element(OSPF_NODE, &ospf_area_nssa_no_summary_cmd);
- install_element(OSPF_NODE, &no_ospf_area_nssa_no_summary_cmd);
- install_element(OSPF_NODE, &ospf_area_nssa_suppress_fa_cmd);
- install_element(OSPF_NODE, &no_ospf_area_nssa_suppress_fa_cmd);
install_element(OSPF_NODE, &no_ospf_area_nssa_cmd);
+ install_element(OSPF_NODE, &ospf_area_nssa_range_cmd);
+ install_element(OSPF_NODE, &no_ospf_area_nssa_range_cmd);
install_element(OSPF_NODE, &ospf_area_default_cost_cmd);
install_element(OSPF_NODE, &no_ospf_area_default_cost_cmd);
@@ -13112,6 +13269,9 @@ void ospf_vty_init(void)
install_element(OSPF_NODE, &flood_reduction_area_cmd);
install_element(OSPF_NODE, &no_flood_reduction_area_cmd);
+ install_element(OSPF_NODE, &ospf_socket_bufsizes_cmd);
+ install_element(OSPF_NODE, &per_intf_socket_cmd);
+
/* Init interface related vty commands. */
ospf_vty_if_init();
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 3e02d3c33e..3f967e41e4 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -20,6 +20,7 @@
#include "log.h"
#include "route_opaque.h"
#include "lib/bfd.h"
+#include "lib/lib_errors.h"
#include "nexthop.h"
#include "ospfd/ospfd.h"
@@ -1470,6 +1471,61 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
return 0;
}
+void ospf_zebra_import_default_route(struct ospf *ospf, bool unreg)
+{
+ struct prefix prefix = {};
+ int command;
+
+ if (zclient->sock < 0) {
+ if (IS_DEBUG_OSPF(zebra, ZEBRA))
+ zlog_debug(" Not connected to Zebra");
+ return;
+ }
+
+ prefix.family = AF_INET;
+ prefix.prefixlen = 0;
+
+ if (unreg)
+ command = ZEBRA_NEXTHOP_UNREGISTER;
+ else
+ command = ZEBRA_NEXTHOP_REGISTER;
+
+ if (IS_DEBUG_OSPF(zebra, ZEBRA))
+ zlog_debug("%s: sending cmd %s for %pFX (vrf %u)", __func__,
+ zserv_command_string(command), &prefix,
+ ospf->vrf_id);
+
+ if (zclient_send_rnh(zclient, command, &prefix, SAFI_UNICAST, false,
+ true, ospf->vrf_id) == ZCLIENT_SEND_FAILURE)
+ flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_send_rnh() failed",
+ __func__);
+}
+
+static int ospf_zebra_import_check_update(ZAPI_CALLBACK_ARGS)
+{
+ struct ospf *ospf;
+ struct zapi_route nhr;
+ struct prefix matched;
+
+ ospf = ospf_lookup_by_vrf_id(vrf_id);
+ if (ospf == NULL || !IS_OSPF_ASBR(ospf))
+ return 0;
+
+ if (!zapi_nexthop_update_decode(zclient->ibuf, &matched, &nhr)) {
+ zlog_err("%s[%u]: Failure to decode route", __func__,
+ ospf->vrf_id);
+ return -1;
+ }
+
+ if (matched.family != AF_INET || matched.prefixlen != 0 ||
+ nhr.type == ZEBRA_ROUTE_OSPF)
+ return 0;
+
+ ospf->nssa_default_import_check.status = !!nhr.nexthop_num;
+ ospf_abr_nssa_type7_defaults(ospf);
+
+ return 0;
+}
int ospf_distribute_list_out_set(struct ospf *ospf, int type, const char *name)
{
@@ -2132,6 +2188,7 @@ static zclient_handler *const ospf_handlers[] = {
[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf_zebra_read_route,
[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf_zebra_read_route,
+ [ZEBRA_NEXTHOP_UPDATE] = ospf_zebra_import_check_update,
[ZEBRA_OPAQUE_MESSAGE] = ospf_opaque_msg_handler,
diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h
index 711b1e7a61..86a5678fc4 100644
--- a/ospfd/ospf_zebra.h
+++ b/ospfd/ospf_zebra.h
@@ -69,6 +69,7 @@ extern int ospf_redistribute_set(struct ospf *, struct ospf_redist *, int,
unsigned short, int, int);
extern int ospf_redistribute_unset(struct ospf *, int, unsigned short);
extern int ospf_redistribute_default_set(struct ospf *, int, int, int);
+extern void ospf_zebra_import_default_route(struct ospf *ospf, bool unreg);
extern int ospf_distribute_list_out_set(struct ospf *, int, const char *);
extern int ospf_distribute_list_out_unset(struct ospf *, int, const char *);
extern void ospf_routemap_set(struct ospf_redist *, const char *);
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 112ddfedb7..7e83714c0a 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -419,6 +419,10 @@ struct ospf *ospf_new_alloc(unsigned short instance, const char *name)
QOBJ_REG(new, ospf);
new->fd = -1;
+ new->intf_socket_enabled = true;
+
+ new->recv_sock_bufsize = OSPF_DEFAULT_SOCK_BUFSIZE;
+ new->send_sock_bufsize = OSPF_DEFAULT_SOCK_BUFSIZE;
return new;
}
@@ -963,6 +967,7 @@ struct ospf_area *ospf_area_new(struct ospf *ospf, struct in_addr area_id)
new->oiflist = list_new();
new->ranges = route_table_init();
+ new->nssa_ranges = route_table_init();
if (area_id.s_addr == OSPF_AREA_BACKBONE)
ospf->backbone = new;
@@ -1006,6 +1011,7 @@ static void ospf_area_free(struct ospf_area *area)
ospf_lsa_unlock(&area->router_lsa_self);
route_table_finish(area->ranges);
+ route_table_finish(area->nssa_ranges);
list_delete(&area->oiflist);
if (EXPORT_NAME(area))
@@ -1029,13 +1035,14 @@ void ospf_area_check_free(struct ospf *ospf, struct in_addr area_id)
struct ospf_area *area;
area = ospf_area_lookup_by_area_id(ospf, area_id);
- if (area && listcount(area->oiflist) == 0 && area->ranges->top == NULL
- && !ospf_vl_count(ospf, area)
- && area->shortcut_configured == OSPF_SHORTCUT_DEFAULT
- && area->external_routing == OSPF_AREA_DEFAULT
- && area->no_summary == 0 && area->default_cost == 1
- && EXPORT_NAME(area) == NULL && IMPORT_NAME(area) == NULL
- && area->auth_type == OSPF_AUTH_NULL) {
+ if (area && listcount(area->oiflist) == 0 &&
+ area->ranges->top == NULL && area->nssa_ranges->top == NULL &&
+ !ospf_vl_count(ospf, area) &&
+ area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
+ area->external_routing == OSPF_AREA_DEFAULT &&
+ area->no_summary == 0 && area->default_cost == 1 &&
+ EXPORT_NAME(area) == NULL && IMPORT_NAME(area) == NULL &&
+ area->auth_type == OSPF_AUTH_NULL) {
listnode_delete(ospf->areas, area);
ospf_area_free(area);
}
@@ -1701,7 +1708,7 @@ int ospf_area_nssa_set(struct ospf *ospf, struct in_addr area_id)
return 1;
}
-int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc)
+int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id)
{
struct ospf_area *area;
@@ -1709,22 +1716,14 @@ int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc)
if (area == NULL)
return 0;
- /* argc < 5 -> 'no area x nssa' */
- if (argc < 5 && area->external_routing == OSPF_AREA_NSSA) {
- ospf->anyNSSA--;
- /* set NSSA area defaults */
- area->no_summary = 0;
- area->suppress_fa = 0;
- area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
- area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
- area->NSSATranslatorStabilityInterval =
- OSPF_NSSA_TRANS_STABLE_DEFAULT;
- ospf_area_type_set(area, OSPF_AREA_DEFAULT);
- } else {
- ospf_area_nssa_translator_role_set(ospf, area_id,
- OSPF_NSSA_ROLE_CANDIDATE);
- }
-
+ ospf->anyNSSA--;
+ /* set NSSA area defaults */
+ area->no_summary = 0;
+ area->suppress_fa = 0;
+ area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
+ area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
+ area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
+ ospf_area_type_set(area, OSPF_AREA_DEFAULT);
ospf_area_check_free(ospf, area_id);
return 1;
@@ -1782,6 +1781,51 @@ int ospf_area_nssa_translator_role_set(struct ospf *ospf,
return 1;
}
+void ospf_area_nssa_default_originate_set(struct ospf *ospf,
+ struct in_addr area_id, int metric,
+ int metric_type)
+{
+ struct ospf_area *area;
+
+ area = ospf_area_lookup_by_area_id(ospf, area_id);
+ if (area == NULL)
+ return;
+
+ if (!area->nssa_default_originate.enabled) {
+ area->nssa_default_originate.enabled = true;
+ if (++ospf->nssa_default_import_check.refcnt == 1) {
+ ospf->nssa_default_import_check.status = false;
+ ospf_zebra_import_default_route(ospf, false);
+ }
+ }
+
+ area->nssa_default_originate.metric_value = metric;
+ area->nssa_default_originate.metric_type = metric_type;
+}
+
+void ospf_area_nssa_default_originate_unset(struct ospf *ospf,
+ struct in_addr area_id)
+{
+ struct ospf_area *area;
+
+ area = ospf_area_lookup_by_area_id(ospf, area_id);
+ if (area == NULL)
+ return;
+
+ if (area->nssa_default_originate.enabled) {
+ area->nssa_default_originate.enabled = false;
+ if (--ospf->nssa_default_import_check.refcnt == 0) {
+ ospf->nssa_default_import_check.status = false;
+ ospf_zebra_import_default_route(ospf, true);
+ }
+ area->nssa_default_originate.metric_value = -1;
+ area->nssa_default_originate.metric_type = -1;
+
+ if (!IS_OSPF_ABR(ospf))
+ ospf_abr_nssa_type7_defaults(ospf);
+ }
+}
+
int ospf_area_export_list_set(struct ospf *ospf, struct ospf_area *area,
const char *list_name)
{
@@ -2140,6 +2184,32 @@ int ospf_nbr_nbma_poll_interval_unset(struct ospf *ospf, struct in_addr addr)
return 1;
}
+/*
+ * Update socket bufsize(s), usually after config change
+ */
+void ospf_update_bufsize(struct ospf *ospf, uint32_t recvsize,
+ uint32_t sendsize)
+{
+ enum ospf_sock_type_e type = OSPF_SOCK_NONE;
+
+ /* Figure out whether there's been a change */
+ if (recvsize != ospf->recv_sock_bufsize) {
+ type = OSPF_SOCK_RECV;
+ ospf->recv_sock_bufsize = recvsize;
+
+ if (sendsize != ospf->send_sock_bufsize) {
+ type = OSPF_SOCK_BOTH;
+ ospf->send_sock_bufsize = sendsize;
+ }
+ } else if (sendsize != ospf->send_sock_bufsize) {
+ type = OSPF_SOCK_SEND;
+ ospf->send_sock_bufsize = sendsize;
+ }
+
+ if (type != OSPF_SOCK_NONE)
+ ospf_sock_bufsize_update(ospf, ospf->fd, type);
+}
+
void ospf_master_init(struct event_loop *master)
{
memset(&ospf_master, 0, sizeof(ospf_master));
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 6727d802a6..1f8d1a32e6 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -67,6 +67,9 @@
#define OSPF_LS_REFRESH_SHIFT (60 * 15)
#define OSPF_LS_REFRESH_JITTER 60
+/* Default socket buffer size */
+#define OSPF_DEFAULT_SOCK_BUFSIZE (8 * 1024 * 1024)
+
struct ospf_external {
unsigned short instance;
struct route_table *external_info;
@@ -302,6 +305,18 @@ struct ospf {
int default_metric; /* Default metric for redistribute. */
+ /* NSSA default-information-originate */
+ struct {
+ /* # of NSSA areas requesting default information */
+ uint16_t refcnt;
+
+ /*
+ * Whether a default route known through non-OSPF protocol is
+ * present in the RIB.
+ */
+ bool status;
+ } nssa_default_import_check;
+
#define OSPF_LSA_REFRESHER_GRANULARITY 10
#define OSPF_LSA_REFRESHER_SLOTS \
((OSPF_LS_REFRESH_TIME + OSPF_LS_REFRESH_SHIFT) \
@@ -412,6 +427,13 @@ struct ospf {
/* Flood Reduction configuration state */
bool fr_configured;
+ /* Socket buffer sizes */
+ uint32_t recv_sock_bufsize;
+ uint32_t send_sock_bufsize;
+
+ /* Per-interface write socket */
+ bool intf_socket_enabled;
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(ospf);
@@ -517,6 +539,7 @@ struct ospf_area {
#define OSPF_TRANSIT_FALSE 0
#define OSPF_TRANSIT_TRUE 1
struct route_table *ranges; /* Configured Area Ranges. */
+ struct route_table *nssa_ranges; /* Configured NSSA Area Ranges. */
/* RFC3137 stub router state flags for area */
uint8_t stub_router_state;
@@ -561,6 +584,13 @@ struct ospf_area {
#define PREFIX_LIST_OUT(A) (A)->plist_out.list
#define PREFIX_NAME_OUT(A) (A)->plist_out.name
+ /* NSSA default-information-originate */
+ struct {
+ bool enabled;
+ int metric_type;
+ int metric_value;
+ } nssa_default_originate;
+
/* Shortest Path Tree. */
struct vertex *spf;
struct list *spf_vertex_list;
@@ -697,14 +727,18 @@ extern int ospf_area_no_summary_set(struct ospf *ospf, struct in_addr area_id);
extern int ospf_area_no_summary_unset(struct ospf *ospf,
struct in_addr area_id);
extern int ospf_area_nssa_set(struct ospf *ospf, struct in_addr area_id);
-extern int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id,
- int argc);
+extern int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id);
extern int ospf_area_nssa_suppress_fa_set(struct ospf *ospf,
struct in_addr area_id);
extern int ospf_area_nssa_suppress_fa_unset(struct ospf *ospf,
struct in_addr area_id);
extern int ospf_area_nssa_translator_role_set(struct ospf *ospf,
struct in_addr area_id, int role);
+extern void ospf_area_nssa_default_originate_set(struct ospf *ospf,
+ struct in_addr area_id,
+ int metric, int metric_type);
+extern void ospf_area_nssa_default_originate_unset(struct ospf *ospf,
+ struct in_addr area_id);
extern int ospf_area_export_list_set(struct ospf *ospf,
struct ospf_area *area_id,
const char *list_name);
@@ -769,6 +803,9 @@ int ospf_area_nssa_no_summary_set(struct ospf *ospf, struct in_addr area_id);
const char *ospf_get_name(const struct ospf *ospf);
extern struct ospf_interface *add_ospf_interface(struct connected *co,
struct ospf_area *area);
+/* Update socket bufsize(s), after config change */
+void ospf_update_bufsize(struct ospf *ospf, uint32_t recvsize,
+ uint32_t sendsize);
extern int p_spaces_compare_func(const struct p_space *a,
const struct p_space *b);