diff options
| -rw-r--r-- | bgpd/bgp_vty.c | 20 | ||||
| -rw-r--r-- | ospf6d/ospf6_nssa.c | 48 | ||||
| -rw-r--r-- | ospfd/ospf_lsa.c | 6 | ||||
| -rw-r--r-- | ospfd/ospf_spf.c | 65 | ||||
| -rw-r--r-- | tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py | 118 |
5 files changed, 235 insertions, 22 deletions
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 7b9400118b..e51977f0f0 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -13003,9 +13003,8 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, if (p->hostname) { if (use_json) { - if (p->hostname) - json_object_string_add(json_neigh, "hostname", - p->hostname); + json_object_string_add(json_neigh, "hostname", + p->hostname); if (p->domainname) json_object_string_add(json_neigh, "domainname", @@ -13017,6 +13016,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, else vty_out(vty, "Hostname: %s\n", p->hostname); } + } else { + if (use_json) + json_object_string_add(json_neigh, "hostname", + "Unknown"); } /* Peer-group */ @@ -14578,6 +14581,17 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, p->shared_network ? "shared network" : "non shared network"); } + } else { + if (use_json) { + json_object_string_add(json_neigh, "nexthop", + "Unknown"); + json_object_string_add(json_neigh, "nexthopGlobal", + "Unknown"); + json_object_string_add(json_neigh, "nexthopLocal", + "Unknown"); + json_object_string_add(json_neigh, "bgpConnection", + "Unknown"); + } } /* Timer information. */ diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index f35c9df4a5..2921046837 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -1090,7 +1090,25 @@ static void ospf6_check_and_originate_type7_lsa(struct ospf6_area *area) ospf6_nssa_lsa_originate(aggr->route, area, true); } } +} + +static void ospf6_ase_lsa_refresh(struct ospf6 *o) +{ + struct ospf6_lsa *old; + for (struct ospf6_route *route = ospf6_route_head(o->external_table); + route; route = ospf6_route_next(route)) { + old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), + route->path.origin.id, o->router_id, + o->lsdb); + if (old) { + THREAD_OFF(old->refresh); + thread_add_event(master, ospf6_lsa_refresh, old, 0, + &old->refresh); + } else { + ospf6_as_external_lsa_originate(route, o); + } + } } void ospf6_area_nssa_update(struct ospf6_area *area) @@ -1134,6 +1152,36 @@ void ospf6_area_nssa_update(struct ospf6_area *area) if (IS_OSPF6_DEBUG_NSSA) zlog_debug("Normal area %s", area->name); ospf6_nssa_flush_area(area); + + /* Check if router is ABR */ + if (ospf6_check_and_set_router_abr(area->ospf6)) { + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug("Router is ABR area %s", area->name); + ospf6_schedule_abr_task(area->ospf6); + ospf6_ase_lsa_refresh(area->ospf6); + } else { + uint16_t type; + struct ospf6_lsa *lsa = NULL; + + /* + * Refresh all type-5 LSAs so they get installed + * in the converted ares + */ + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug("Refresh type-5 LSAs, area %s", + area->name); + + type = htons(OSPF6_LSTYPE_AS_EXTERNAL); + for (ALL_LSDB_TYPED_ADVRTR(area->ospf6->lsdb, type, + area->ospf6->router_id, + lsa)) { + if (IS_OSPF6_DEBUG_NSSA) + ospf6_lsa_header_print(lsa); + THREAD_OFF(lsa->refresh); + thread_add_event(master, ospf6_lsa_refresh, lsa, + 0, &lsa->refresh); + } + } } } diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 92558e3c51..ad4a9fd142 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -428,8 +428,10 @@ struct ospf_neighbor *ospf_nbr_lookup_ptop(struct ospf_interface *oi) /* PtoP link must have only 1 neighbor. */ if (ospf_nbr_count(oi, 0) > 1) - flog_warn(EC_OSPF_PTP_NEIGHBOR, - "Point-to-Point link has more than 1 neighobrs."); + flog_warn( + EC_OSPF_PTP_NEIGHBOR, + "Point-to-Point link on interface %s has more than 1 neighbor.", + oi->ifp->name); return nbr; } diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 24ca4dcbf4..4f60ce22a9 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -181,8 +181,10 @@ static struct vertex_parent *vertex_parent_new(struct vertex *v, int backlink, return new; } -static void vertex_parent_free(void *p) +static void vertex_parent_free(struct vertex_parent *p) { + vertex_nexthop_free(p->local_nexthop); + vertex_nexthop_free(p->nexthop); XFREE(MTYPE_OSPF_VERTEX_PARENT, p); } @@ -205,7 +207,7 @@ static struct vertex *ospf_vertex_new(struct ospf_area *area, new->lsa = lsa->data; new->children = list_new(); new->parents = list_new(); - new->parents->del = vertex_parent_free; + new->parents->del = (void (*)(void *))vertex_parent_free; new->parents->cmp = vertex_parent_cmp; new->lsa_p = lsa; @@ -348,7 +350,7 @@ static struct vertex *ospf_spf_vertex_copy(struct vertex *vertex) memcpy(copy, vertex, sizeof(struct vertex)); copy->parents = list_new(); - copy->parents->del = vertex_parent_free; + copy->parents->del = (void (*)(void *))vertex_parent_free; copy->parents->cmp = vertex_parent_cmp; copy->children = list_new(); @@ -685,11 +687,15 @@ static void ospf_spf_flush_parents(struct vertex *w) /* * Consider supplied next-hop for inclusion to the supplied list of * equal-cost next-hops, adjust list as necessary. + * + * Returns vertex parent pointer if created otherwise `NULL` if it already + * exists. */ -static void ospf_spf_add_parent(struct vertex *v, struct vertex *w, - struct vertex_nexthop *newhop, - struct vertex_nexthop *newlhop, - unsigned int distance) +static struct vertex_parent *ospf_spf_add_parent(struct vertex *v, + struct vertex *w, + struct vertex_nexthop *newhop, + struct vertex_nexthop *newlhop, + unsigned int distance) { struct vertex_parent *vp, *wp; struct listnode *node; @@ -735,7 +741,8 @@ static void ospf_spf_add_parent(struct vertex *v, struct vertex *w, zlog_debug( "%s: ... nexthop already on parent list, skipping add", __func__); - return; + + return NULL; } } @@ -743,7 +750,7 @@ static void ospf_spf_add_parent(struct vertex *v, struct vertex *w, newlhop); listnode_add_sort(w->parents, vp); - return; + return vp; } static int match_stub_prefix(struct lsa_header *lsa, struct in_addr v_link_addr, @@ -981,8 +988,12 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area, memcpy(lnh, nh, sizeof(struct vertex_nexthop)); - ospf_spf_add_parent(v, w, nh, lnh, - distance); + if (ospf_spf_add_parent(v, w, nh, lnh, + distance) == + NULL) { + vertex_nexthop_free(nh); + vertex_nexthop_free(lnh); + } return 1; } else zlog_info( @@ -1021,8 +1032,13 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area, memcpy(lnh, nh, sizeof(struct vertex_nexthop)); - ospf_spf_add_parent(v, w, nh, lnh, - distance); + if (ospf_spf_add_parent(v, w, nh, lnh, + distance) == + NULL) { + vertex_nexthop_free(nh); + vertex_nexthop_free(lnh); + } + return 1; } else zlog_info( @@ -1045,7 +1061,12 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area, lnh = vertex_nexthop_new(); memcpy(lnh, nh, sizeof(struct vertex_nexthop)); - ospf_spf_add_parent(v, w, nh, lnh, distance); + if (ospf_spf_add_parent(v, w, nh, lnh, distance) == + NULL) { + vertex_nexthop_free(nh); + vertex_nexthop_free(lnh); + } + return 1; } } /* end V is the root */ @@ -1088,8 +1109,12 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area, sizeof(struct vertex_nexthop)); added = 1; - ospf_spf_add_parent(v, w, nh, lnh, - distance); + if (ospf_spf_add_parent(v, w, nh, lnh, + distance) == + NULL) { + vertex_nexthop_free(nh); + vertex_nexthop_free(lnh); + } } /* * Note lack of return is deliberate. See next @@ -1150,7 +1175,13 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area, lnh = NULL; } - ospf_spf_add_parent(v, w, vp->nexthop, lnh, distance); + nh = vertex_nexthop_new(); + *nh = *vp->nexthop; + + if (ospf_spf_add_parent(v, w, nh, lnh, distance) == NULL) { + vertex_nexthop_free(nh); + vertex_nexthop_free(lnh); + } } return added; diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py index 7b41c80ce3..35c28b8a07 100644 --- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py @@ -406,6 +406,124 @@ def test_ospfv3_nssa_tc26_p0(request): write_test_footer(tc_name) +def test_ospfv3_learning_tc15_p0(request): + """Verify OSPF can learn different types of LSA and processes them. + + OSPF Learning : Edge learning different types of LSAs. + """ + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + check_router_status(tgen) + + global topo + step("Bring up the base config as per the topology") + step("Configure area 1 as NSSA Area") + + reset_config_on_routers(tgen) + + step("Verify that Type 3 summary LSA is originated for the same Area 0") + ip = topo["routers"]["r1"]["links"]["r3-link0"]["ipv6"] + ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + + input_dict = { + "r1": { + "static_routes": [ + { + "network": ip_net, + "no_of_ip": 1, + "routeType": "Network", + "pathtype": "Inter-Area", + } + ] + } + } + + dut = "r0" + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf6" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r2": { + "static_routes": [ + {"network": NETWORK["ipv6"][0], "no_of_ip": 5, "next_hop": "Null0"} + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Redistribute static route in R2 ospf.") + dut = "r2" + red_static(dut) + + step("Verify that Type 5 LSA is originated by R2.") + dut = "r0" + protocol = "ospf6" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r1": { + "static_routes": [ + {"network": NETWORK["ipv6"][0], "no_of_ip": 1, "routeType": "Network"} + ] + } + } + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_ospf6_neighbor(tgen, topo) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Change area 1 as non nssa area (on the fly changing area" " type on DUT).") + + for rtr in ["r1", "r2", "r3"]: + input_dict = { + rtr: { + "ospf6": {"area": [{"id": "0.0.0.2", "type": "nssa", "delete": True}]} + } + } + result = create_router_ospf(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Verify that OSPF neighbours are reset after changing area type.") + step("Verify that ABR R2 originates type 5 LSA in area 1.") + step("Verify that R1 installs type 5 lsa in its database.") + step("Verify that route is calculated and installed in R1.") + + input_dict = { + "r1": { + "static_routes": [ + {"network": NETWORK["ipv6"][0], "no_of_ip": 1, "routeType": "Network"} + ] + } + } + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + # As per internal discussion, this script has to be removed as translator # function is not supported, for more details kindly check this PR 2565570 def ospfv3_nssa_tc27_p0(request): |
