diff options
Diffstat (limited to 'ospfd')
| -rw-r--r-- | ospfd/ospf_abr.c | 324 | ||||
| -rw-r--r-- | ospfd/ospf_abr.h | 25 | ||||
| -rw-r--r-- | ospfd/ospf_interface.c | 28 | ||||
| -rw-r--r-- | ospfd/ospf_interface.h | 3 | ||||
| -rw-r--r-- | ospfd/ospf_lsa.c | 128 | ||||
| -rw-r--r-- | ospfd/ospf_lsa.h | 5 | ||||
| -rw-r--r-- | ospfd/ospf_network.c | 136 | ||||
| -rw-r--r-- | ospfd/ospf_network.h | 15 | ||||
| -rw-r--r-- | ospfd/ospf_packet.c | 23 | ||||
| -rw-r--r-- | ospfd/ospf_route.c | 14 | ||||
| -rw-r--r-- | ospfd/ospf_route.h | 5 | ||||
| -rw-r--r-- | ospfd/ospf_routemap.c | 8 | ||||
| -rw-r--r-- | ospfd/ospf_snmp.c | 2 | ||||
| -rw-r--r-- | ospfd/ospf_te.c | 20 | ||||
| -rw-r--r-- | ospfd/ospf_vty.c | 504 | ||||
| -rw-r--r-- | ospfd/ospf_zebra.c | 57 | ||||
| -rw-r--r-- | ospfd/ospf_zebra.h | 1 | ||||
| -rw-r--r-- | ospfd/ospfd.c | 118 | ||||
| -rw-r--r-- | ospfd/ospfd.h | 41 |
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); |
