diff options
38 files changed, 644 insertions, 701 deletions
diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c index 641cc7605f..7dda4f0180 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -440,7 +440,7 @@ bool config_bgp_aspath_validate(const char *regstr) } DEFUN(as_path, bgp_as_path_cmd, - "bgp as-path access-list WORD [seq (0-4294967295)] <deny|permit> LINE...", + "bgp as-path access-list AS_PATH_FILTER_NAME [seq (0-4294967295)] <deny|permit> LINE...", BGP_STR "BGP autonomous system path filter\n" "Specify an access list name\n" @@ -460,7 +460,7 @@ DEFUN(as_path, bgp_as_path_cmd, int64_t seqnum = ASPATH_SEQ_NUMBER_AUTO; /* Retrieve access list name */ - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "AS_PATH_FILTER_NAME", &idx); char *alname = argv[idx]->arg; if (argv_find(argv, argc, "(0-4294967295)", &idx)) @@ -509,7 +509,7 @@ DEFUN(as_path, bgp_as_path_cmd, } DEFUN(no_as_path, no_bgp_as_path_cmd, - "no bgp as-path access-list WORD [seq (0-4294967295)] <deny|permit> LINE...", + "no bgp as-path access-list AS_PATH_FILTER_NAME [seq (0-4294967295)] <deny|permit> LINE...", NO_STR BGP_STR "BGP autonomous system path filter\n" @@ -529,7 +529,7 @@ DEFUN(no_as_path, no_bgp_as_path_cmd, regex_t *regex; char *aslistname = - argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; + argv_find(argv, argc, "AS_PATH_FILTER_NAME", &idx) ? argv[idx]->arg : NULL; /* Lookup AS list from AS path list. */ aslist = as_list_lookup(aslistname); @@ -586,7 +586,7 @@ DEFUN(no_as_path, no_bgp_as_path_cmd, DEFUN (no_as_path_all, no_bgp_as_path_all_cmd, - "no bgp as-path access-list WORD", + "no bgp as-path access-list AS_PATH_FILTER_NAME", NO_STR BGP_STR "BGP autonomous system path filter\n" @@ -653,7 +653,7 @@ static void as_list_show_all(struct vty *vty, json_object *json) DEFUN (show_as_path_access_list, show_bgp_as_path_access_list_cmd, - "show bgp as-path-access-list WORD [json]", + "show bgp as-path-access-list AS_PATH_FILTER_NAME [json]", SHOW_STR BGP_STR "List AS path access lists\n" @@ -684,7 +684,7 @@ DEFUN (show_as_path_access_list, ALIAS (show_as_path_access_list, show_ip_as_path_access_list_cmd, - "show ip as-path-access-list WORD [json]", + "show ip as-path-access-list AS_PATH_FILTER_NAME [json]", SHOW_STR IP_STR "List AS path access lists\n" @@ -753,6 +753,20 @@ static struct cmd_node as_list_node = { .config_write = config_write_as_list, }; +static void bgp_aspath_filter_cmd_completion(vector comps, + struct cmd_token *token) +{ + struct as_list *aslist; + + for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, aslist->name)); +} + +static const struct cmd_variable_handler aspath_filter_handlers[] = { + {.tokenname = "AS_PATH_FILTER_NAME", + .completions = bgp_aspath_filter_cmd_completion}, + {.completions = NULL}}; + /* Register functions. */ void bgp_filter_init(void) { @@ -766,6 +780,8 @@ void bgp_filter_init(void) install_element(VIEW_NODE, &show_ip_as_path_access_list_cmd); install_element(VIEW_NODE, &show_bgp_as_path_access_list_all_cmd); install_element(VIEW_NODE, &show_ip_as_path_access_list_all_cmd); + + cmd_variable_handler_register(aspath_filter_handlers); } void bgp_filter_reset(void) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 0eb3cc61e3..e1d4d22b7e 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -12007,7 +12007,7 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd, <[all$all] dampening <parameters>\ |route-map WORD\ |prefix-list WORD\ - |filter-list WORD\ + |filter-list AS_PATH_FILTER_NAME\ |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\ |A.B.C.D/M longer-prefixes\ |X:X::X:X/M longer-prefixes\ diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 2f37367a8f..75dbc7f3e3 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -4927,7 +4927,7 @@ DEFUN_YANG (no_match_ecommunity, DEFUN_YANG (match_aspath, match_aspath_cmd, - "match as-path WORD", + "match as-path AS_PATH_FILTER_NAME", MATCH_STR "Match BGP AS path list\n" "AS path access-list name\n") @@ -4950,7 +4950,7 @@ DEFUN_YANG (match_aspath, DEFUN_YANG (no_match_aspath, no_match_aspath_cmd, - "no match as-path [WORD]", + "no match as-path [AS_PATH_FILTER_NAME]", NO_STR MATCH_STR "Match BGP AS path list\n" diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 26da38bd7a..8e2044fd8a 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7242,7 +7242,7 @@ static int peer_aslist_unset_vty(struct vty *vty, const char *ip_str, afi_t afi, DEFUN (neighbor_filter_list, neighbor_filter_list_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> filter-list WORD <in|out>", + "neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Establish BGP filters\n" @@ -7259,7 +7259,7 @@ DEFUN (neighbor_filter_list, } ALIAS_HIDDEN(neighbor_filter_list, neighbor_filter_list_hidden_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> filter-list WORD <in|out>", + "neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Establish BGP filters\n" "AS path access-list name\n" @@ -7268,7 +7268,7 @@ ALIAS_HIDDEN(neighbor_filter_list, neighbor_filter_list_hidden_cmd, DEFUN (no_neighbor_filter_list, no_neighbor_filter_list_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> filter-list WORD <in|out>", + "no neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 @@ -7285,7 +7285,7 @@ DEFUN (no_neighbor_filter_list, } ALIAS_HIDDEN(no_neighbor_filter_list, no_neighbor_filter_list_hidden_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> filter-list WORD <in|out>", + "no neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Establish BGP filters\n" "AS path access-list name\n" diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index 0b718fcdf2..624510323c 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -181,7 +181,7 @@ OSPF6 area The `not-advertise` option, when present, prevents the summary route from being advertised, effectively filtering the summarized routes. -.. clicmd:: area A.B.C.D nssa [no-summary] +.. clicmd:: area A.B.C.D nssa [no-summary] [default-information-originate [metric-type (1-2)] [metric (0-16777214)]] .. clicmd:: area (0-4294967295) nssa [no-summary] [default-information-originate [metric-type (1-2)] [metric (0-16777214)]] @@ -209,6 +209,21 @@ OSPF6 area existence of a default route in the RIB that wasn't learned via the OSPF protocol. +.. clicmd:: area A.B.C.D nssa range X:X::X:X/M [<not-advertise|cost (0-16777215)>] + +.. clicmd:: area (0-4294967295) nssa range X:X::X:X/M [<not-advertise|cost (0-16777215)>] + + Summarize a group of external subnets into a single Type-7 LSA, which is + then translated to a Type-5 LSA and avertised to the backbone. + This command can only be used at the area boundary (NSSA ABR router). + + By default, the metric of the summary route is calculated as the highest + metric among the summarized routes. The `cost` option, however, can be used + to set an explicit metric. + + The `not-advertise` option, when present, prevents the summary route from + being advertised, effectively filtering the summarized routes. + .. clicmd:: area A.B.C.D export-list NAME .. clicmd:: area (0-4294967295) export-list NAME @@ -45,6 +45,7 @@ DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected"); DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label"); DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters"); +static void if_set_name(struct interface *ifp, const char *name); static struct interface *if_lookup_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); static int if_cmp_func(const struct interface *, const struct interface *); @@ -153,16 +154,19 @@ static void ifp_connected_free(void *arg) } /* Create new interface structure. */ -static struct interface *if_new(vrf_id_t vrf_id) +static struct interface *if_new(struct vrf *vrf) { struct interface *ifp; + assert(vrf); + ifp = XCALLOC(MTYPE_IF, sizeof(struct interface)); ifp->ifindex = IFINDEX_INTERNAL; ifp->name[0] = '\0'; - ifp->vrf_id = vrf_id; + ifp->vrf = vrf; + ifp->vrf_id = vrf->vrf_id; ifp->connected = list_new(); ifp->connected->del = ifp_connected_free; @@ -207,11 +211,11 @@ void if_down_via_zapi(struct interface *ifp) (*ifp_master.down_hook)(ifp); } -struct interface *if_create_name(const char *name, vrf_id_t vrf_id) +static struct interface *if_create_name(const char *name, struct vrf *vrf) { struct interface *ifp; - ifp = if_new(vrf_id); + ifp = if_new(vrf); if_set_name(ifp, name); @@ -219,35 +223,23 @@ struct interface *if_create_name(const char *name, vrf_id_t vrf_id) return ifp; } -struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id) -{ - struct interface *ifp; - - ifp = if_new(vrf_id); - - if_set_index(ifp, ifindex); - - hook_call(if_add, ifp); - return ifp; -} - /* Create new interface structure. */ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) { struct vrf *old_vrf, *vrf; /* remove interface from old master vrf list */ - old_vrf = vrf_lookup_by_id(ifp->vrf_id); - if (old_vrf) { - if (ifp->name[0] != '\0') - IFNAME_RB_REMOVE(old_vrf, ifp); + old_vrf = ifp->vrf; - if (ifp->ifindex != IFINDEX_INTERNAL) - IFINDEX_RB_REMOVE(old_vrf, ifp); - } + if (ifp->name[0] != '\0') + IFNAME_RB_REMOVE(old_vrf, ifp); + + if (ifp->ifindex != IFINDEX_INTERNAL) + IFINDEX_RB_REMOVE(old_vrf, ifp); ifp->vrf_id = vrf_id; vrf = vrf_get(ifp->vrf_id, NULL); + ifp->vrf = vrf; if (ifp->name[0] != '\0') IFNAME_RB_INSERT(vrf, ifp); @@ -261,7 +253,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) * the interface and readding it in the new VRF, which would have * several implications. */ - if (yang_module_find("frr-interface")) { + if (!vrf_is_backend_netns() && yang_module_find("frr-interface")) { struct lyd_node *if_dnode; char oldpath[XPATH_MAXLEN]; char newpath[XPATH_MAXLEN]; @@ -304,15 +296,15 @@ void if_delete_retain(struct interface *ifp) void if_delete(struct interface **ifp) { struct interface *ptr = *ifp; - struct vrf *vrf; - - vrf = vrf_lookup_by_id(ptr->vrf_id); - assert(vrf); + struct vrf *vrf = ptr->vrf; IFNAME_RB_REMOVE(vrf, ptr); if (ptr->ifindex != IFINDEX_INTERNAL) IFINDEX_RB_REMOVE(vrf, ptr); + if (!vrf_is_enabled(vrf)) + vrf_delete(vrf); + if_delete_retain(ptr); list_delete(&ptr->connected); @@ -439,7 +431,7 @@ struct interface *if_lookup_by_name_all_vrf(const char *name) if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ) return NULL; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { ifp = if_lookup_by_name_vrf(name, vrf); if (ifp) return ifp; @@ -582,72 +574,58 @@ size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz, /* Get interface by name if given name interface doesn't exist create one. */ -struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id) +struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id, + const char *vrf_name) { - struct interface *ifp; + struct interface *ifp = NULL; + struct vrf *vrf; switch (vrf_get_backend()) { case VRF_BACKEND_UNKNOWN: case VRF_BACKEND_NETNS: - ifp = if_lookup_by_name(name, vrf_id); - if (ifp) - return ifp; - return if_create_name(name, vrf_id); - case VRF_BACKEND_VRF_LITE: - ifp = if_lookup_by_name_all_vrf(name); + vrf = vrf_get(vrf_id, vrf_name); + assert(vrf); + + ifp = if_lookup_by_name_vrf(name, vrf); if (ifp) { - if (ifp->vrf_id == vrf_id) - return ifp; /* If it came from the kernel or by way of zclient, * believe it and update the ifp accordingly. */ - if_update_to_new_vrf(ifp, vrf_id); + if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN) + if_update_to_new_vrf(ifp, vrf_id); + return ifp; } - return if_create_name(name, vrf_id); - } - return NULL; -} - -struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id) -{ - struct interface *ifp; - - switch (vrf_get_backend()) { - case VRF_BACKEND_UNKNOWN: - case VRF_BACKEND_NETNS: - ifp = if_lookup_by_ifindex(ifindex, vrf_id); - if (ifp) - return ifp; - return if_create_ifindex(ifindex, vrf_id); + break; case VRF_BACKEND_VRF_LITE: - ifp = if_lookup_by_index_all_vrf(ifindex); + ifp = if_lookup_by_name_all_vrf(name); if (ifp) { - if (ifp->vrf_id == vrf_id) - return ifp; /* If it came from the kernel or by way of zclient, * believe it and update the ifp accordingly. */ - if_update_to_new_vrf(ifp, vrf_id); + if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN) + if_update_to_new_vrf(ifp, vrf_id); + return ifp; } - return if_create_ifindex(ifindex, vrf_id); + + vrf = vrf_get(vrf_id, vrf_name); + assert(vrf); + + break; + default: + return NULL; } - return NULL; + return if_create_name(name, vrf); } int if_set_index(struct interface *ifp, ifindex_t ifindex) { - struct vrf *vrf; - if (ifp->ifindex == ifindex) return 0; - vrf = vrf_get(ifp->vrf_id, NULL); - assert(vrf); - /* * If there is already an interface with this ifindex, we will collide * on insertion, so don't even try. @@ -656,7 +634,7 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex) return -1; if (ifp->ifindex != IFINDEX_INTERNAL) - IFINDEX_RB_REMOVE(vrf, ifp); + IFINDEX_RB_REMOVE(ifp->vrf, ifp); ifp->ifindex = ifindex; @@ -666,30 +644,25 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex) * already an interface with the desired ifindex at the top of * the function. Nevertheless. */ - if (IFINDEX_RB_INSERT(vrf, ifp)) + if (IFINDEX_RB_INSERT(ifp->vrf, ifp)) return -1; } return 0; } -void if_set_name(struct interface *ifp, const char *name) +static void if_set_name(struct interface *ifp, const char *name) { - struct vrf *vrf; - - vrf = vrf_get(ifp->vrf_id, NULL); - assert(vrf); - if (if_cmp_name_func(ifp->name, name) == 0) return; if (ifp->name[0] != '\0') - IFNAME_RB_REMOVE(vrf, ifp); + IFNAME_RB_REMOVE(ifp->vrf, ifp); strlcpy(ifp->name, name, sizeof(ifp->name)); if (ifp->name[0] != '\0') - IFNAME_RB_INSERT(vrf, ifp); + IFNAME_RB_INSERT(ifp->vrf, ifp); } /* Does interface up ? */ @@ -817,15 +790,12 @@ static void if_dump(const struct interface *ifp) struct listnode *node; struct connected *c __attribute__((unused)); - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) { - struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id); - + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) zlog_info( "Interface %s vrf %s(%u) index %d metric %d mtu %d mtu6 %d %s", - ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex, + ifp->name, ifp->vrf->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu, ifp->mtu6, if_flag_dump(ifp->flags)); - } } /* Interface printing for all interface. */ @@ -894,16 +864,14 @@ connected_log(struct connected *connected, char *str) { struct prefix *p; struct interface *ifp; - struct vrf *vrf; char logbuf[BUFSIZ]; char buf[BUFSIZ]; ifp = connected->ifp; p = connected->address; - vrf = vrf_lookup_by_id(ifp->vrf_id); snprintf(logbuf, sizeof(logbuf), "%s interface %s vrf %s(%u) %s %pFX ", - str, ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, + str, ifp->name, ifp->vrf->name, ifp->vrf_id, prefix_family_str(p), p); p = connected->destination; @@ -1059,30 +1027,15 @@ struct connected *connected_get_linklocal(struct interface *ifp) void if_terminate(struct vrf *vrf) { struct interface *ifp; - bool delete; - - /* - * If the default VRF is being terminated or has - * already been terminated it means that - * the program is shutting down and we need to - * delete all the interfaces. Otherwise, we only - * need to move VRF's interfaces to the default VRF. - */ - delete = vrf_is_backend_netns() || vrf->vrf_id == VRF_DEFAULT - || !vrf_lookup_by_id(VRF_DEFAULT); while (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) { ifp = RB_ROOT(if_name_head, &vrf->ifaces_by_name); - if (delete) { - if (ifp->node) { - ifp->node->info = NULL; - route_unlock_node(ifp->node); - } - if_delete(&ifp); - } else { - if_update_to_new_vrf(ifp, VRF_DEFAULT); + if (ifp->node) { + ifp->node->info = NULL; + route_unlock_node(ifp->node); } + if_delete(&ifp); } } @@ -1186,6 +1139,25 @@ void if_link_params_free(struct interface *ifp) /* ----------- CLI commands ----------- */ +/* Guess the VRF of an interface. */ +static int vrfname_by_ifname(const char *ifname, const char **vrfname) +{ + struct vrf *vrf; + struct interface *ifp; + int count = 0; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + FOR_ALL_INTERFACES (vrf, ifp) { + if (strmatch(ifp->name, ifname)) { + *vrfname = vrf->name; + count++; + } + } + } + + return count; +} + /* * XPath: /frr-interface:lib/interface */ @@ -1197,12 +1169,9 @@ DEFPY_YANG_NOSH (interface, VRF_CMD_HELP_STR) { char xpath_list[XPATH_MAXLEN]; - vrf_id_t vrf_id; struct interface *ifp; - int ret; - - if (!vrf_name) - vrf_name = VRF_DEFAULT_NAME; + struct vrf *vrf; + int ret, count; /* * This command requires special handling to maintain backward @@ -1211,30 +1180,30 @@ DEFPY_YANG_NOSH (interface, * interface is found, then a new one should be created on the default * VRF. */ - VRF_GET_ID(vrf_id, vrf_name, false); - ifp = if_lookup_by_name_all_vrf(ifname); - if (ifp && ifp->vrf_id != vrf_id) { - struct vrf *vrf; - + if (vrf_is_backend_netns()) { /* - * Special case 1: a VRF name was specified, but the found - * interface is associated to different VRF. Reject the command. + * For backward compatibility, if the VRF name is not specified + * and there is exactly one interface with this name in the + * system, use its VRF. Otherwise fallback to the default VRF. */ - if (vrf_id != VRF_DEFAULT) { - vty_out(vty, "%% interface %s not in %s vrf\n", ifname, - vrf_name); - return CMD_WARNING_CONFIG_FAILED; + if (!vrf_name) { + count = vrfname_by_ifname(ifname, &vrf_name); + if (count != 1) + vrf_name = VRF_DEFAULT_NAME; } - + } else { /* - * Special case 2: a VRF name was *not* specified, and the found - * interface is associated to a VRF other than the default one. - * Update vrf_id and vrf_name to account for that. + * If the interface already exists, use its VRF regardless of + * what user specified. We can't have same interface name in + * different VRFs with VRF-lite backend. */ - vrf = vrf_lookup_by_id(ifp->vrf_id); - assert(vrf); - vrf_id = ifp->vrf_id; - vrf_name = vrf->name; + ifp = if_lookup_by_name_all_vrf(ifname); + if (ifp) { + vrf_name = ifp->vrf->name; + } else { + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; + } } snprintf(xpath_list, sizeof(xpath_list), @@ -1252,7 +1221,15 @@ DEFPY_YANG_NOSH (interface, * all interface-level commands are converted to the new * northbound model. */ - ifp = if_lookup_by_name(ifname, vrf_id); + if (vrf_is_backend_netns()) { + vrf = vrf_lookup_by_name(vrf_name); + if (vrf) + ifp = if_lookup_by_name_vrf(ifname, vrf); + else + ifp = NULL; + } else { + ifp = if_lookup_by_name_all_vrf(ifname); + } if (ifp) VTY_PUSH_CONTEXT(INTERFACE_NODE, ifp); } @@ -1397,7 +1374,6 @@ static int lib_interface_create(struct nb_cb_create_args *args) { const char *ifname; const char *vrfname; - struct vrf *vrf; struct interface *ifp; ifname = yang_dnode_get_string(args->dnode, "./name"); @@ -1405,39 +1381,11 @@ static int lib_interface_create(struct nb_cb_create_args *args) switch (args->event) { case NB_EV_VALIDATE: - vrf = vrf_lookup_by_name(vrfname); - if (!vrf) { - zlog_warn("%s: VRF %s doesn't exist", __func__, - vrfname); - return NB_ERR_VALIDATION; - } - if (vrf->vrf_id == VRF_UNKNOWN) { - zlog_warn("%s: VRF %s is not active", __func__, - vrf->name); - return NB_ERR_VALIDATION; - } - - /* if VRF is netns or not yet known - init for instance - * then assumption is that passed config is exact - * then the user intent was not to use an other iface - */ - if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) { - ifp = if_lookup_by_name_all_vrf(ifname); - if (ifp && ifp->vrf_id != vrf->vrf_id) { - zlog_warn( - "%s: interface %s already exists in another VRF", - __func__, ifp->name); - return NB_ERR_VALIDATION; - } - } - break; case NB_EV_PREPARE: case NB_EV_ABORT: break; case NB_EV_APPLY: - vrf = vrf_lookup_by_name(vrfname); - assert(vrf); - ifp = if_get_by_name(ifname, vrf->vrf_id); + ifp = if_get_by_name(ifname, VRF_UNKNOWN, vrfname); ifp->configured = true; nb_running_set_entry(args->dnode, ifp); @@ -1488,7 +1436,7 @@ static const void *lib_interface_get_next(struct nb_cb_get_next_args *args) assert(vrf); pif = RB_MIN(if_name_head, &vrf->ifaces_by_name); } else { - vrf = vrf_lookup_by_id(pif->vrf_id); + vrf = pif->vrf; pif = RB_NEXT(if_name_head, pif); /* if no more interfaces, switch to next vrf */ while (pif == NULL) { @@ -1506,13 +1454,9 @@ static int lib_interface_get_keys(struct nb_cb_get_keys_args *args) { const struct interface *ifp = args->list_entry; - struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id); - - assert(vrf); - args->keys->num = 2; strlcpy(args->keys->key[0], ifp->name, sizeof(args->keys->key[0])); - strlcpy(args->keys->key[1], vrf->name, sizeof(args->keys->key[1])); + strlcpy(args->keys->key[1], ifp->vrf->name, sizeof(args->keys->key[1])); return NB_OK; } @@ -293,6 +293,8 @@ struct interface { #endif /* HAVE_NET_RT_IFLIST */ struct route_node *node; + + struct vrf *vrf; vrf_id_t vrf_id; /* @@ -510,11 +512,6 @@ extern int if_cmp_name_func(const char *p1, const char *p2); */ extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id); -/* Create new interface, adds to name list only */ -extern struct interface *if_create_name(const char *name, vrf_id_t vrf_id); - -/* Create new interface, adds to index list only */ -extern struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id); extern struct interface *if_vrf_lookup_by_index_next(ifindex_t ifindex, vrf_id_t vrf_id); @@ -532,13 +529,11 @@ struct vrf; extern struct interface *if_lookup_by_name_all_vrf(const char *ifname); extern struct interface *if_lookup_by_name_vrf(const char *name, struct vrf *vrf); extern struct interface *if_lookup_by_name(const char *ifname, vrf_id_t vrf_id); -extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id); -extern struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); +extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id, + const char *vrf_name); /* Sets the index and adds to index list */ extern int if_set_index(struct interface *ifp, ifindex_t ifindex); -/* Sets the name and adds to name list */ -extern void if_set_name(struct interface *ifp, const char *name); /* Delete the interface, but do not free the structure, and leave it in the interface list. It is often advisable to leave the pseudo interface @@ -272,32 +272,29 @@ void vrf_delete(struct vrf *vrf) if (vrf_is_enabled(vrf)) vrf_disable(vrf); + if (vrf->vrf_id != VRF_UNKNOWN) { + RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); + vrf->vrf_id = VRF_UNKNOWN; + } + /* If the VRF is user configured, it'll stick around, just remove * the ID mapping. Interfaces assigned to this VRF should've been * removed already as part of the VRF going down. */ if (vrf_is_user_cfged(vrf)) { - if (vrf->vrf_id != VRF_UNKNOWN) { - /* Delete any VRF interfaces - should be only - * the VRF itself, other interfaces should've - * been moved out of the VRF. - */ - if_terminate(vrf); - RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); - vrf->vrf_id = VRF_UNKNOWN; - } vrf->ns_ctxt = NULL; return; } + /* Do not delete the VRF if it has interfaces configured in it. */ + if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) + return; + if (vrf_master.vrf_delete_hook) (*vrf_master.vrf_delete_hook)(vrf); QOBJ_UNREG(vrf); - if_terminate(vrf); - if (vrf->vrf_id != VRF_UNKNOWN) - RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); if (vrf->name[0] != '\0') RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf); @@ -571,6 +568,7 @@ static void vrf_terminate_single(struct vrf *vrf) { /* Clear configured flag and invoke delete. */ UNSET_FLAG(vrf->status, VRF_CONFIGURED); + if_terminate(vrf); vrf_delete(vrf); } diff --git a/lib/zclient.c b/lib/zclient.c index d639fa84b8..eea118738c 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -2164,19 +2164,21 @@ static int zclient_interface_add(struct zclient *zclient, vrf_id_t vrf_id) struct interface *ifp; char ifname_tmp[INTERFACE_NAMSIZ + 1] = {}; struct stream *s = zclient->ibuf; + struct vrf *vrf; /* Read interface name. */ STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ); /* Lookup/create interface by name. */ - if (!vrf_get(vrf_id, NULL)) { + vrf = vrf_lookup_by_id(vrf_id); + if (!vrf) { zlog_debug( "Rx'd interface add from Zebra, but VRF %u does not exist", vrf_id); return -1; } - ifp = if_get_by_name(ifname_tmp, vrf_id); + ifp = if_get_by_name(ifname_tmp, vrf_id, vrf->name); zebra_interface_if_set_value(s, ifp); diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index f3e8127a80..a9b4c7756c 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -106,8 +106,7 @@ static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route, return 0; } -static void ospf6_abr_delete_route(struct ospf6_route *range, - struct ospf6_route *summary, +static void ospf6_abr_delete_route(struct ospf6_route *summary, struct ospf6_route_table *summary_table, struct ospf6_lsa *old) { @@ -385,8 +384,8 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "The range is not active. withdraw"); - ospf6_abr_delete_route(route, summary, - summary_table, old); + ospf6_abr_delete_route(summary, summary_table, + old); } } else if (old) { ospf6_route_remove(summary, summary_table); @@ -400,7 +399,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "Area has been stubbed, purge Inter-Router LSA"); - ospf6_abr_delete_route(route, summary, summary_table, old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -409,7 +408,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug("Area has been stubbed, purge prefix LSA"); - ospf6_abr_delete_route(route, summary, summary_table, old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -444,8 +443,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug( "This is the secondary path to the ASBR, ignore"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -475,8 +473,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "Suppressed by range %pFX of area %s", &range->prefix, route_area->name); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } } @@ -488,8 +485,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug( "This is the range with DoNotAdvertise set. ignore"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -497,8 +493,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) { if (is_debug) zlog_debug("The range is not active. withdraw"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } } @@ -608,10 +603,14 @@ void ospf6_abr_range_reset_cost(struct ospf6 *ospf6) struct ospf6_area *oa; struct ospf6_route *range; - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) + for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) { for (range = ospf6_route_head(oa->range_table); range; range = ospf6_route_next(range)) OSPF6_ABR_RANGE_CLEAR_COST(range); + for (range = ospf6_route_head(oa->nssa_range_table); range; + range = ospf6_route_next(range)) + OSPF6_ABR_RANGE_CLEAR_COST(range); + } } static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range, @@ -622,10 +621,19 @@ static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range, for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro; ro = ospf6_route_match_next(&range->prefix, ro)) { - if (ro->path.area_id == range->path.area_id - && (ro->path.type == OSPF6_PATH_TYPE_INTRA) - && !CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE)) - cost = MAX(cost, ro->path.cost); + if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE)) + continue; + if (ro->path.area_id != range->path.area_id) + continue; + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE) + && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1 + && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2) + continue; + if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE) + && ro->path.type != OSPF6_PATH_TYPE_INTRA) + continue; + + cost = MAX(cost, ro->path.cost); } return cost; @@ -674,6 +682,8 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6) int summary_orig = 0; assert(range->type == OSPF6_DEST_TYPE_RANGE); + oa = ospf6_area_lookup(range->path.area_id, ospf6); + assert(oa); /* update range's cost and active flag */ cost = ospf6_abr_range_compute_cost(range, ospf6); @@ -696,34 +706,49 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6) * if there * were active ranges. */ + if (!ospf6_abr_range_summary_needs_update(range, cost)) + return; - if (ospf6_abr_range_summary_needs_update(range, cost)) { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("%s: range %pFX update", __func__, - &range->prefix); - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("%s: range %pFX update", __func__, &range->prefix); + + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) { + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) + && !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) { + ospf6_nssa_lsa_originate(range, oa, true); + summary_orig = 1; + } else { + struct ospf6_lsa *lsa; + + lsa = ospf6_lsdb_lookup(range->path.origin.type, + range->path.origin.id, + ospf6->router_id, oa->lsdb); + if (lsa) + ospf6_lsa_premature_aging(lsa); + } + } else { + for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) { summary_orig += ospf6_abr_originate_summary_to_area(range, oa); + } + } - if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) - && summary_orig) { - if (!CHECK_FLAG(range->flag, - OSPF6_ROUTE_BLACKHOLE_ADDED)) { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("Add discard route"); + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) + && summary_orig) { + if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("Add discard route"); - ospf6_zebra_add_discard(range, ospf6); - } - } else { - /* Summary removed or no summary generated as no - * specifics exist */ - if (CHECK_FLAG(range->flag, - OSPF6_ROUTE_BLACKHOLE_ADDED)) { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("Delete discard route"); + ospf6_zebra_add_discard(range, ospf6); + } + } else { + /* Summary removed or no summary generated as no + * specifics exist */ + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("Delete discard route"); - ospf6_zebra_delete_discard(range, ospf6); - } + ospf6_zebra_delete_discard(range, ospf6); } } } diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index 999266b8d1..996892c49c 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -306,7 +306,8 @@ struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df) oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES); oa->range_table->scope = oa; - bf_init(oa->range_table->idspace, 32); + oa->nssa_range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES); + oa->nssa_range_table->scope = oa; oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES); oa->summary_prefix->scope = oa; oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS); @@ -361,6 +362,7 @@ void ospf6_area_delete(struct ospf6_area *oa) ospf6_route_table_delete(oa->route_table); ospf6_route_table_delete(oa->range_table); + ospf6_route_table_delete(oa->nssa_range_table); ospf6_route_table_delete(oa->summary_prefix); ospf6_route_table_delete(oa->summary_router); @@ -576,8 +578,6 @@ DEFUN (area_range, range->path.u.cost_config = cost; - zlog_debug("%s: for prefix %s, flag = %x", __func__, - argv[idx_ipv6_prefixlen]->arg, range->flag); if (range->rnode == NULL) { ospf6_route_add(range, oa->range_table); } @@ -694,6 +694,22 @@ void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6) vty_out(vty, " no-summary"); vty_out(vty, "\n"); } + for (range = ospf6_route_head(oa->nssa_range_table); range; + range = ospf6_route_next(range)) { + vty_out(vty, " area %s nssa range %pFX", oa->name, + &range->prefix); + + if (CHECK_FLAG(range->flag, + OSPF6_ROUTE_DO_NOT_ADVERTISE)) { + vty_out(vty, " not-advertise"); + } else { + if (range->path.u.cost_config + != OSPF_AREA_RANGE_COST_UNSPEC) + vty_out(vty, " cost %u", + range->path.u.cost_config); + } + vty_out(vty, "\n"); + } if (PREFIX_NAME_IN(oa)) vty_out(vty, " area %s filter-list prefix %s in\n", oa->name, PREFIX_NAME_IN(oa)); diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h index 77cbad8b9e..905fbac949 100644 --- a/ospf6d/ospf6_area.h +++ b/ospf6d/ospf6_area.h @@ -46,6 +46,7 @@ struct ospf6_area { /* Summary routes to be originated (includes Configured Address Ranges) */ struct ospf6_route_table *range_table; + struct ospf6_route_table *nssa_range_table; struct ospf6_route_table *summary_prefix; struct ospf6_route_table *summary_router; diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 150903a56a..6e00bd766f 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -266,10 +266,14 @@ void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa) /* RFC2328 section 13.2 Installing LSAs in the database */ void ospf6_install_lsa(struct ospf6_lsa *lsa) { + struct ospf6 *ospf6; struct timeval now; struct ospf6_lsa *old; struct ospf6_area *area = NULL; + ospf6 = ospf6_get_by_lsdb(lsa); + assert(ospf6); + /* Remove the old instance from all neighbors' Link state retransmission list (RFC2328 13.2 last paragraph) */ old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, @@ -330,20 +334,14 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa) && !CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)) { /* check if it is new lsa ? or existing lsa got modified ?*/ - if (!old || OSPF6_LSA_IS_CHANGED(old, lsa)) { - struct ospf6 *ospf6; - - ospf6 = ospf6_get_by_lsdb(lsa); - - assert(ospf6); - + if (!old || OSPF6_LSA_IS_CHANGED(old, lsa)) ospf6_helper_handle_topo_chg(ospf6, lsa); - } } ospf6_lsdb_add(lsa, lsa->lsdb); - if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7) { + if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7 + && lsa->header->adv_router != ospf6->router_id) { area = OSPF6_AREA(lsa->lsdb->data); ospf6_translated_nssa_refresh(area, lsa, NULL); ospf6_schedule_abr_task(area->ospf6); diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 9d73740819..64992bbcee 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -1241,7 +1241,6 @@ struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp) { struct listnode *n; struct connected *c; - struct in6_addr *l = (struct in6_addr *)NULL; /* for each connected address */ for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) { @@ -1250,9 +1249,10 @@ struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp) continue; if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)) - l = &c->address->u.prefix6; + return &c->address->u.prefix6; } - return l; + + return NULL; } diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index f406e828e1..77f0f8f4e5 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -1070,7 +1070,7 @@ DEFPY (debug_ospf6_lsa_aggregation, DEFUN (debug_ospf6_lsa_type, debug_ospf6_lsa_hex_cmd, - "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]", + "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]", DEBUG_STR OSPF6_STR "Debug Link State Advertisements (LSAs)\n" @@ -1079,6 +1079,7 @@ DEFUN (debug_ospf6_lsa_type, "Display Inter-Area-Prefix LSAs\n" "Display Inter-Router LSAs\n" "Display As-External LSAs\n" + "Display NSSA LSAs\n" "Display Link LSAs\n" "Display Intra-Area-Prefix LSAs\n" "Display LSAs of unknown origin\n" @@ -1122,7 +1123,7 @@ DEFUN (debug_ospf6_lsa_type, DEFUN (no_debug_ospf6_lsa_type, no_debug_ospf6_lsa_hex_cmd, - "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]", + "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]", NO_STR DEBUG_STR OSPF6_STR @@ -1132,6 +1133,7 @@ DEFUN (no_debug_ospf6_lsa_type, "Display Inter-Area-Prefix LSAs\n" "Display Inter-Router LSAs\n" "Display As-External LSAs\n" + "Display NSSA LSAs\n" "Display Link LSAs\n" "Display Intra-Area-Prefix LSAs\n" "Display LSAs of unknown origin\n" diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h index 2316040694..c0d3cc149b 100644 --- a/ospf6d/ospf6_lsa.h +++ b/ospf6d/ospf6_lsa.h @@ -87,11 +87,6 @@ #define OSPF6_SCOPE_AS 0x4000 #define OSPF6_SCOPE_RESERVED 0x6000 -/* AS-external-LSA refresh method. */ -#define LSA_REFRESH_IF_CHANGED 0 -#define LSA_REFRESH_FORCE 1 - - /* XXX U-bit handling should be treated here */ #define OSPF6_LSA_SCOPE(type) (ntohs(type) & OSPF6_LSTYPE_SCOPE_MASK) diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 6f2795a56d..36948dc0a7 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -48,7 +48,7 @@ #include "ospf6_gr.h" #include "lib/json.h" -DEFINE_MTYPE(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor"); +DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor"); DEFINE_HOOK(ospf6_neighbor_change, (struct ospf6_neighbor * on, int state, int next_state), diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index c2e9b7f28a..84f014d680 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -49,6 +49,9 @@ #include "ospf6_asbr.h" #include "ospf6d.h" #include "ospf6_nssa.h" +#ifndef VTYSH_EXTRACT_PL +#include "ospf6d/ospf6_nssa_clippy.c" +#endif DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA"); unsigned char config_debug_ospf6_nssa = 0; @@ -262,22 +265,20 @@ static void ospf6_abr_announce_aggregates(struct ospf6 *ospf6) { struct ospf6_area *area; struct ospf6_route *range; - struct listnode *node, *nnode; + struct listnode *node; if (IS_OSPF6_DEBUG_ABR) zlog_debug("ospf6_abr_announce_aggregates(): Start"); - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) { - for (range = ospf6_route_head(area->range_table); range; - range = ospf6_route_next(range)) - ospf6_abr_range_update(range, ospf6); - } - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) { if (IS_OSPF6_DEBUG_ABR) zlog_debug( "ospf_abr_announce_aggregates(): looking at area %pI4", &area->area_id); + + for (range = ospf6_route_head(area->range_table); range; + range = ospf6_route_next(range)) + ospf6_abr_range_update(range, ospf6); } if (IS_OSPF6_DEBUG_ABR) @@ -381,22 +382,18 @@ static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6) { struct ospf6_lsa *lsa; uint16_t type; - struct ospf6_area *oa; - struct listnode *node; if (IS_OSPF6_DEBUG_NSSA) zlog_debug("ospf6_abr_unapprove_translates(): Start"); type = htons(OSPF6_LSTYPE_AS_EXTERNAL); - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { - for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) { - if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) { - SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED); - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "%s : approved unset on link id %pI4", - __func__, &lsa->header->id); - } + for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) { + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) { + SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED); + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug( + "%s : approved unset on link id %pI4", + __func__, &lsa->header->id); } } @@ -408,17 +405,17 @@ static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6) static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, struct ospf6_lsa *type7) { - char *buffer; + char buffer[OSPF6_MAX_LSASIZE]; struct ospf6_lsa *lsa; struct ospf6_as_external_lsa *ext, *extnew; struct ospf6_lsa_header *lsa_header; caddr_t old_ptr, new_ptr; struct ospf6_as_external_lsa *nssa; struct prefix prefix; - struct ospf6_route *match; struct ospf6 *ospf6 = area->ospf6; ptrdiff_t tag_offset = 0; route_tag_t network_order; + struct ospf6_route *range; if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : Start", __func__); @@ -430,7 +427,27 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, return NULL; } - buffer = XCALLOC(MTYPE_OSPF6_LSA, OSPF6_MAX_LSASIZE); + /* find the translated Type-5 for this Type-7 */ + nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( + type7->header); + prefix.family = AF_INET6; + prefix.prefixlen = nssa->prefix.prefix_length; + ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix); + + /* Check if the Type-7 LSA should be suppressed by aggregation. */ + range = ospf6_route_lookup_bestmatch(&prefix, area->nssa_range_table); + if (range && !prefix_same(&prefix, &range->prefix) + && !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) { + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug( + "%s: LSA %s suppressed by range %pFX of area %s", + __func__, type7->name, &range->prefix, + area->name); + return NULL; + } + + /* prepare buffer */ + memset(buffer, 0, sizeof(buffer)); lsa_header = (struct ospf6_lsa_header *)buffer; extnew = (struct ospf6_as_external_lsa *)((caddr_t)lsa_header @@ -445,23 +462,6 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, memcpy(extnew, ext, sizeof(struct ospf6_as_external_lsa)); - /* find the translated Type-5 for this Type-7 */ - nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( - type7->header); - - prefix.family = AF_INET6; - prefix.prefixlen = nssa->prefix.prefix_length; - ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix); - - /* Find the LSA from the external route */ - match = ospf6_route_lookup(&prefix, area->route_table); - if (match == NULL) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : no matching route %pFX", __func__, - &prefix); - return NULL; - } - /* set Prefix */ memcpy(new_ptr, old_ptr, OSPF6_PREFIX_SPACE(ext->prefix.prefix_length)); ospf6_prefix_apply_mask(&extnew->prefix); @@ -542,7 +542,6 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, struct ospf6_lsa *type5) { struct ospf6_lsa *new = NULL; - struct ospf6_as_external_lsa *ext_lsa; struct prefix prefix; struct ospf6 *ospf6 = area->ospf6; @@ -554,27 +553,27 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, /* Find the AS external LSA */ if (type5 == NULL) { + struct ospf6_as_external_lsa *ext_lsa; + struct ospf6_route *match; + + /* Find the AS external LSA from Type-7 LSA */ if (IS_OSPF6_DEBUG_NSSA) zlog_debug( - "%s: No translated Type-5 found for Type-7 with Id %pI4", - __func__, &type7->header->id); + "%s: try to find translated Type-5 LSA for %s", + __func__, type7->name); - /* find the translated Type-5 for this Type-7 */ ext_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( type7->header); - prefix.family = AF_INET6; prefix.prefixlen = ext_lsa->prefix.prefix_length; ospf6_prefix_in6_addr(&prefix.u.prefix6, ext_lsa, &ext_lsa->prefix); - /* Find the AS external LSA from Type-7 LSA */ - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s: try to find external LSA id %d", - __func__, type7->external_lsa_id); - type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - type7->external_lsa_id, - ospf6->router_id, ospf6->lsdb); + match = ospf6_route_lookup(&prefix, ospf6->external_table); + if (match) + type5 = ospf6_lsdb_lookup( + OSPF6_LSTYPE_AS_EXTERNAL, match->path.origin.id, + ospf6->router_id, ospf6->lsdb); } if (type5) { @@ -602,6 +601,7 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, __func__, &type7->header->id); return NULL; } + UNSET_FLAG(new->flag, OSPF6_LSA_UNAPPROVED); } if (IS_OSPF6_DEBUG_NSSA) @@ -610,32 +610,11 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, return new; } -/* Originate Translated Type-5 for supplied Type-7 NSSA LSA */ -struct ospf6_lsa *ospf6_translated_nssa_originate(struct ospf6_area *oa, - struct ospf6_lsa *type7) -{ - struct ospf6_lsa *new; - - if (ntohs(type7->header->type) != OSPF6_LSTYPE_TYPE_7) - return NULL; - - if ((new = ospf6_lsa_translated_nssa_new(oa, type7)) == NULL) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "%s : Could not translate Type-7, Id %pI4, to Type-5", - __func__, &type7->header->id); - return NULL; - } - - return new; -} - -int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) +static void ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) { /* Incoming Type-7 or later aggregated Type-7 * * LSA is skipped if P-bit is off. - * LSA is aggregated if within range. * * The Type-7 is translated, Installed/Approved as a Type-5 into * global LSDB, then Flooded through AS @@ -659,7 +638,7 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) zlog_debug( "%s : LSA Id %pI4, P-bit off, NO Translation", __func__, &lsa->header->id); - return 1; + return; } if (IS_OSPF6_DEBUG_NSSA) @@ -676,7 +655,7 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) zlog_debug( "%s : LSA Id %pI4, Forward address is 0, NO Translation", __func__, &lsa->header->id); - return 1; + return; } /* Find the existing AS-External LSA for this prefix */ @@ -687,23 +666,13 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) ospf6->lsdb); } - /* Check Type 5 LSA using the matching external ID */ - if (old == NULL) { - old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - lsa->external_lsa_id, ospf6->router_id, - ospf6->lsdb); + if (OSPF6_LSA_IS_MAXAGE(lsa)) { + if (old) + ospf6_lsa_premature_aging(old); + return; } if (old) { - /* Do not continue if type 5 LSA not approved */ - if (CHECK_FLAG(old->flag, OSPF6_LSA_UNAPPROVED)) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "%s : LSA Id %pI4 type 5 is not approved", - __func__, &old->header->id); - return 1; - } - if (IS_OSPF6_DEBUG_NSSA) zlog_debug( "%s : found old translated LSA Id %pI4, refreshing", @@ -722,16 +691,14 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) * originate translated LSA */ - if (ospf6_translated_nssa_originate(area, lsa) == NULL) { + if (ospf6_lsa_translated_nssa_new(area, lsa) == NULL) { if (IS_OSPF6_DEBUG_NSSA) zlog_debug( "%s : Could not translate Type-7 for %pI4 to Type-5", __func__, &lsa->header->id); - return 1; + return; } } - - return 0; } static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) @@ -751,6 +718,8 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) zlog_debug("%s : Start", __func__); for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + if (!IS_AREA_NSSA(oa)) + continue; /* skip if not translator */ if (oa->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) { @@ -760,13 +729,6 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) continue; } - /* skip if not Nssa Area */ - if (!IS_AREA_NSSA(oa)) { - zlog_debug("%s area %pI4 Flag %x", __func__, - &oa->area_id, oa->flag); - continue; - } - if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : looking at area %pI4", __func__, &oa->area_id); @@ -784,71 +746,30 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) zlog_debug("%s : Stop", __func__); } -/* Generate translated type-5 LSA from the configured area ranges*/ -static void ospf6_abr_translate_nssa_range(struct ospf6 *ospf6) -{ - struct listnode *node, *nnode; - struct ospf6_area *oa; - struct ospf6_route *range; - struct ospf6_lsa *lsa; - - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) { - for (range = ospf6_route_head(oa->range_table); range; - range = ospf6_route_next(range)) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "Translating range %pFX of area %pI4", - &range->prefix, &oa->area_id); - if (CHECK_FLAG(range->flag, - OSPF6_ROUTE_DO_NOT_ADVERTISE)) - continue; - - /* Find the NSSA LSA from the route */ - /* Generate and flood external LSA */ - lsa = ospf6_lsdb_lookup(OSPF6_LSTYPE_TYPE_7, - range->path.origin.id, - ospf6->router_id, oa->lsdb); - if (lsa) - ospf6_abr_translate_nssa(oa, lsa); - } - } -} - static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6) { struct listnode *node; struct ospf6_area *area; + struct ospf6_route *range; if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : Start", __func__); + zlog_debug("%s: Start", __func__); for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) { if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) continue; if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : looking at area %pI4", __func__, + zlog_debug("%s: looking at area %pI4", __func__, &area->area_id); - ospf6_abr_translate_nssa_range(ospf6); + for (range = ospf6_route_head(area->nssa_range_table); range; + range = ospf6_route_next(range)) + ospf6_abr_range_update(range, ospf6); } if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : Stop", __func__); -} - -/*Flood max age LSA's for the unapproved LSA's */ -static int ospf6_abr_remove_unapproved_translates_apply(struct ospf6_lsa *lsa) -{ - if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT) - && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) { - zlog_debug("%s : removing unapproved translates, lsa : %s", - __func__, lsa->name); - - /* FLUSH THROUGHOUT AS */ - ospf6_lsa_premature_aging(lsa); - } - return 0; + zlog_debug("%s: Stop", __func__); } static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6) @@ -862,8 +783,16 @@ static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6) zlog_debug("ospf6_abr_remove_unapproved_translates(): Start"); type = htons(OSPF6_LSTYPE_AS_EXTERNAL); - for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) - ospf6_abr_remove_unapproved_translates_apply(lsa); + for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) { + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT) + && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) { + zlog_debug( + "%s : removing unapproved translates, lsa : %s", + __func__, lsa->name); + + ospf6_lsa_premature_aging(lsa); + } + } if (IS_OSPF6_DEBUG_NSSA) zlog_debug("ospf_abr_remove_unapproved_translates(): Stop"); @@ -948,11 +877,6 @@ void ospf6_abr_nssa_type_7_defaults(struct ospf6 *ospf6) static void ospf6_abr_nssa_task(struct ospf6 *ospf6) { - /* called only if any_nssa */ - struct ospf6_route *range; - struct ospf6_area *area; - struct listnode *node, *nnode; - if (IS_OSPF6_DEBUG_NSSA) zlog_debug("Check for NSSA-ABR Tasks():"); @@ -978,10 +902,10 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6) ospf6_abr_unapprove_translates(ospf6); - /* RESET all Ranges in every Area, same as summaries */ + /* Originate Type-7 aggregates */ if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("ospf6_abr_nssa_task(): NSSA initialize aggregates"); - ospf6_abr_range_reset_cost(ospf6); + zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates"); + ospf6_abr_send_nssa_aggregates(ospf6); /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or * Aggregate as Type-7 @@ -991,32 +915,12 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6) zlog_debug("ospf6_abr_nssa_task(): process translates"); ospf6_abr_process_nssa_translates(ospf6); - /* Translate/Send any "ranged" aggregates, and also 5-Install and - * Approve - * Scan Type-7's for aggregates, translate to Type-5's, - * Install/Flood/Approve - */ - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates"); - ospf6_abr_send_nssa_aggregates(ospf6); /*TURNED OFF FOR NOW */ - /* Flush any unapproved previous translates from Global Data Base */ if (IS_OSPF6_DEBUG_NSSA) zlog_debug( "ospf6_abr_nssa_task(): remove unapproved translates"); ospf6_abr_remove_unapproved_translates(ospf6); - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) { - for (range = ospf6_route_head(area->range_table); range; - range = ospf6_route_next(range)) { - if (CHECK_FLAG(range->flag, - OSPF6_ROUTE_DO_NOT_ADVERTISE)) - ospf6_zebra_delete_discard(range, ospf6); - else - ospf6_zebra_add_discard(range, ospf6); - } - } - if (IS_OSPF6_DEBUG_NSSA) zlog_debug("ospf6_abr_nssa_task(): Stop"); } @@ -1063,106 +967,6 @@ int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route, return 1; } -static void ospf6_external_lsa_refresh_type(struct ospf6 *ospf6, uint8_t type, - unsigned short instance, int force) -{ - struct ospf6_route *route; - struct ospf6_external_info *info; - struct ospf6_lsa *lsa; - - if (type == ZEBRA_ROUTE_MAX) - return; - - for (route = ospf6_route_head(ospf6->external_table); route; - route = ospf6_route_next(route)) { - info = route->route_option; - - /* Find the external LSA in the database */ - if (!is_default_prefix(&route->prefix)) { - lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - htonl(info->id), - ospf6->router_id, ospf6->lsdb); - - if (lsa) { - THREAD_OFF(lsa->refresh); - - /* LSA is maxage, immediate refresh */ - if (OSPF6_LSA_IS_MAXAGE(lsa)) - ospf6_flood(NULL, lsa); - else - thread_add_timer(master, - ospf6_lsa_refresh, lsa, - OSPF_LS_REFRESH_TIME, - &lsa->refresh); - } else { - /* LSA not found in the database - * Verify and originate external LSA - */ - if (ospf6_redistribute_check(ospf6, route, - type)) - ospf6_as_external_lsa_originate(route, - ospf6); - } - } - } -} - -/* Refresh default route */ -static void ospf6_external_lsa_refresh_default(struct ospf6 *ospf6) -{ - struct ospf6_route *route; - struct ospf6_external_info *info; - struct ospf6_lsa *lsa; - - for (route = ospf6_route_head(ospf6->external_table); route; - route = ospf6_route_next(route)) { - if (is_default_prefix(&route->prefix)) { - info = route->route_option; - lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - htonl(info->id), - ospf6->router_id, ospf6->lsdb); - - if (lsa) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", - (void *)lsa); - if (OSPF6_LSA_IS_MAXAGE(lsa)) - ospf6_flood(NULL, lsa); - else - thread_add_timer(master, - ospf6_lsa_refresh, lsa, - OSPF_LS_REFRESH_TIME, - &lsa->refresh); - } else if (!lsa) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "LSA[Type5:0.0.0.0]: Originate AS-external-LSA"); - ospf6_as_external_lsa_originate(route, ospf6); - } - } - } -} - -/* If there's redistribution configured, we need to refresh external - * LSAs in order to install Type-7 and flood to all NSSA Areas - */ -void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6) -{ - int type; - struct ospf6_redist *red; - - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { - red = ospf6_redist_lookup(ospf6, type, 0); - if (!red) - return; - - ospf6_external_lsa_refresh_type(ospf6, type, red->instance, - LSA_REFRESH_IF_CHANGED); - } - ospf6_external_lsa_refresh_default(ospf6); -} - /* This function performs ABR related processing */ static int ospf6_abr_task_timer(struct thread *thread) { @@ -1176,7 +980,6 @@ static int ospf6_abr_task_timer(struct thread *thread) ospf6_abr_task(ospf6); /* if nssa-abr, then scan Type-7 LSDB */ ospf6_abr_nssa_task(ospf6); - ospf6_asbr_nssa_redist_task(ospf6); return 0; } @@ -1337,6 +1140,13 @@ int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area) UNSET_FLAG(area->flag, OSPF6_AREA_NSSA); if (IS_OSPF6_DEBUG_NSSA) zlog_debug("area %s nssa reset", area->name); + + /* Clear the table of NSSA ranges. */ + ospf6_route_table_delete(area->nssa_range_table); + area->nssa_range_table = + OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES); + area->nssa_range_table->scope = area; + ospf6_area_nssa_update(area); } @@ -1350,10 +1160,14 @@ static struct in6_addr *ospf6_get_nssa_fwd_addr(struct ospf6_area *oa) struct ospf6_interface *oi; for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) { - if (if_is_operative(oi->interface)) - if (oi->area && IS_AREA_NSSA(oi->area)) - return ospf6_interface_get_global_address( - oi->interface); + struct in6_addr *addr; + + if (!if_is_operative(oi->interface)) + continue; + + addr = ospf6_interface_get_global_address(oi->interface); + if (addr) + return addr; } return NULL; } @@ -1463,17 +1277,119 @@ void ospf6_abr_check_translate_nssa(struct ospf6_area *area, if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : start", __func__); + if (!ospf6_check_and_set_router_abr(ospf6)) + return; + type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), lsa->external_lsa_id, ospf6->router_id, ospf6->lsdb); - - if (ospf6_check_and_set_router_abr(ospf6) && (type5 == NULL)) { + if (!type5) { if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : Originating type5 LSA", __func__); ospf6_lsa_translated_nssa_new(area, lsa); } } +DEFPY (area_nssa_range, + area_nssa_range_cmd, + "area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]", + "OSPF6 area parameters\n" + "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" + "Configure OSPF6 area as nssa\n" + "Configured address range\n" + "Specify IPv6 prefix\n" + "Do not advertise\n" + "User specified metric for this range\n" + "Advertised metric for this range\n") +{ + struct ospf6_area *oa; + struct ospf6_route *range; + + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + OSPF6_CMD_AREA_GET(area, oa, ospf6); + + if (!IS_AREA_NSSA(oa)) { + vty_out(vty, "%% First configure %s as an NSSA area\n", area); + return CMD_WARNING; + } + + range = ospf6_route_lookup((struct prefix *)prefix, + oa->nssa_range_table); + if (range == NULL) { + range = ospf6_route_create(ospf6); + range->type = OSPF6_DEST_TYPE_RANGE; + SET_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE); + prefix_copy(&range->prefix, prefix); + range->path.area_id = oa->area_id; + range->path.metric_type = 2; + range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC; + range->path.origin.type = htons(OSPF6_LSTYPE_TYPE_7); + range->path.origin.id = htonl(ospf6->external_id++); + range->path.origin.adv_router = ospf6->router_id; + ospf6_route_add(range, oa->nssa_range_table); + } + + /* process "not-advertise" */ + if (not_adv) + SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + else + UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + + /* process "cost" */ + if (!cost_str) + cost = OSPF_AREA_RANGE_COST_UNSPEC; + range->path.u.cost_config = cost; + + /* Redo summaries if required */ + if (ospf6_check_and_set_router_abr(ospf6)) + ospf6_schedule_abr_task(ospf6); + + return CMD_SUCCESS; +} + +DEFPY (no_area_nssa_range, + no_area_nssa_range_cmd, + "no area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise|cost (0-16777215)>]", + NO_STR + "OSPF6 area parameters\n" + "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" + "Configure OSPF6 area as nssa\n" + "Configured address range\n" + "Specify IPv6 prefix\n" + "Do not advertise\n" + "User specified metric for this range\n" + "Advertised metric for this range\n") +{ + struct ospf6_area *oa; + struct ospf6_route *range; + + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + OSPF6_CMD_AREA_GET(area, oa, ospf6); + + range = ospf6_route_lookup((struct prefix *)prefix, + oa->nssa_range_table); + if (range == NULL) { + vty_out(vty, "%% range %s does not exists.\n", prefix_str); + return CMD_SUCCESS; + } + + if (ospf6_check_and_set_router_abr(oa->ospf6)) { + /* Blow away the aggregated LSA and route */ + SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE); + + /* Redo summaries if required */ + thread_execute(master, ospf6_abr_task_timer, ospf6, 0); + } + + ospf6_route_remove(range, oa->nssa_range_table); + + return CMD_SUCCESS; +} + DEFUN(debug_ospf6_nssa, debug_ospf6_nssa_cmd, "debug ospf6 nssa", DEBUG_STR @@ -1503,6 +1419,9 @@ void config_write_ospf6_debug_nssa(struct vty *vty) void install_element_ospf6_debug_nssa(void) { + install_element(OSPF6_NODE, &area_nssa_range_cmd); + install_element(OSPF6_NODE, &no_area_nssa_range_cmd); + install_element(ENABLE_NODE, &debug_ospf6_nssa_cmd); install_element(ENABLE_NODE, &no_debug_ospf6_nssa_cmd); install_element(CONFIG_NODE, &debug_ospf6_nssa_cmd); diff --git a/ospf6d/ospf6_nssa.h b/ospf6d/ospf6_nssa.h index 99cb04c003..02234cc8bd 100644 --- a/ospf6d/ospf6_nssa.h +++ b/ospf6d/ospf6_nssa.h @@ -55,8 +55,6 @@ extern void ospf6_nssa_lsa_flush(struct ospf6 *ospf6, struct prefix_ipv6 *p); extern struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *oa, struct ospf6_lsa *type7, struct ospf6_lsa *type5); -extern struct ospf6_lsa * -ospf6_translated_nssa_originate(struct ospf6_area *oa, struct ospf6_lsa *type7); extern void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6); @@ -69,8 +67,6 @@ extern void install_element_ospf6_debug_nssa(void); extern void ospf6_abr_nssa_type_7_defaults(struct ospf6 *osof6); int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route, int type); -extern int ospf6_abr_translate_nssa(struct ospf6_area *area, - struct ospf6_lsa *lsa); extern void ospf6_abr_check_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa); extern void ospf6_abr_nssa_check_status(struct ospf6 *ospf6); diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 4b87c4cf30..a4ed99ea2d 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -1098,7 +1098,6 @@ struct ospf6_route_table *ospf6_route_table_create(int s, int t) void ospf6_route_table_delete(struct ospf6_route_table *table) { ospf6_route_remove_all(table); - bf_free(table->idspace); route_table_finish(table->table); XFREE(MTYPE_OSPF6_ROUTE_TABLE, table); } diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index e29439b95e..fd8b6a9c1d 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -186,7 +186,7 @@ struct ospf6_route { struct timeval changed; /* flag */ - uint8_t flag; + uint16_t flag; /* Prefix Options */ uint8_t prefix_options; @@ -221,14 +221,15 @@ struct ospf6_route { #define OSPF6_DEST_TYPE_RANGE 5 #define OSPF6_DEST_TYPE_MAX 6 -#define OSPF6_ROUTE_CHANGE 0x01 -#define OSPF6_ROUTE_ADD 0x02 -#define OSPF6_ROUTE_REMOVE 0x04 -#define OSPF6_ROUTE_BEST 0x08 -#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x10 -#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x20 -#define OSPF6_ROUTE_WAS_REMOVED 0x40 -#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x80 +#define OSPF6_ROUTE_CHANGE 0x0001 +#define OSPF6_ROUTE_ADD 0x0002 +#define OSPF6_ROUTE_REMOVE 0x0004 +#define OSPF6_ROUTE_BEST 0x0008 +#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x0010 +#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x0020 +#define OSPF6_ROUTE_WAS_REMOVED 0x0040 +#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x0080 +#define OSPF6_ROUTE_NSSA_RANGE 0x0100 struct ospf6; struct ospf6_route_table { @@ -241,8 +242,6 @@ struct ospf6_route_table { uint32_t count; - bitfield_t idspace; - /* hooks */ void (*hook_add)(struct ospf6_route *); void (*hook_change)(struct ospf6_route *); diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 9e3bb4895a..7e9ed4160d 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -1032,7 +1032,6 @@ DEFUN_HIDDEN (ospf6_interface_area, struct ospf6_area *oa; struct ospf6_interface *oi; struct interface *ifp; - vrf_id_t vrf_id = VRF_DEFAULT; uint32_t area_id; int format; @@ -1041,11 +1040,8 @@ DEFUN_HIDDEN (ospf6_interface_area, vty_out(vty, "Please, use \"ipv6 ospf6 area\" on an interface instead.\n"); - if (ospf6->vrf_id != VRF_UNKNOWN) - vrf_id = ospf6->vrf_id; - /* find/create ospf6 interface */ - ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id); + ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name); oi = (struct ospf6_interface *)ifp->info; if (oi == NULL) oi = ospf6_interface_create(ifp); @@ -1107,18 +1103,14 @@ DEFUN_HIDDEN (no_ospf6_interface_area, struct ospf6_area *oa; struct interface *ifp; uint32_t area_id; - vrf_id_t vrf_id = VRF_DEFAULT; vty_out(vty, "This command is deprecated, because it is not VRF-aware.\n"); vty_out(vty, "Please, use \"no ipv6 ospf6 area\" on an interface instead.\n"); - if (ospf6->vrf_id != VRF_UNKNOWN) - vrf_id = ospf6->vrf_id; - /* find/create ospf6 interface */ - ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id); + ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name); if (ifp == NULL) { vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg); diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am index be626646a0..34aabc205b 100644 --- a/ospf6d/subdir.am +++ b/ospf6d/subdir.am @@ -99,6 +99,7 @@ clippy_scan += \ ospf6d/ospf6_lsa.c \ ospf6d/ospf6_gr_helper.c \ ospf6d/ospf6_gr.c \ + ospf6d/ospf6_nssa.c \ ospf6d/ospf6_route.c \ # end diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 81cc346000..60e109ea80 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -915,9 +915,9 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf, ospf->vrf_id); snprintf(ifname, sizeof(ifname), "VLINK%u", vlink_count); - vi = if_create_name(ifname, ospf->vrf_id); + vi = if_get_by_name(ifname, ospf->vrf_id, ospf->name); /* - * if_create_name sets ZEBRA_INTERFACE_LINKDETECTION + * if_get_by_name sets ZEBRA_INTERFACE_LINKDETECTION * virtual links don't need this. */ UNSET_FLAG(vi->status, ZEBRA_INTERFACE_LINKDETECTION); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 9863a10115..64d3b7a028 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -445,7 +445,7 @@ DEFUN_HIDDEN (ospf_passive_interface_addr, "Please, use \"ip ospf passive\" on an interface instead.\n"); if (ospf->vrf_id != VRF_UNKNOWN) - ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id); + ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id, ospf->name); if (ifp == NULL) { vty_out(vty, "interface %s not found.\n", (char *)argv[1]->arg); @@ -506,7 +506,7 @@ DEFUN_HIDDEN (no_ospf_passive_interface, "Please, use \"no ip ospf passive\" on an interface instead.\n"); if (ospf->vrf_id != VRF_UNKNOWN) - ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id); + ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id, ospf->name); if (ifp == NULL) { vty_out(vty, "interface %s not found.\n", (char *)argv[2]->arg); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index eb19cf4ddf..5e311d101a 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1482,7 +1482,8 @@ void pim_if_create_pimreg(struct pim_instance *pim) snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u", pim->vrf->data.l.table_id); - pim->regiface = if_create_name(pimreg_name, pim->vrf->vrf_id); + pim->regiface = if_get_by_name(pimreg_name, pim->vrf->vrf_id, + pim->vrf->name); pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; pim_if_new(pim->regiface, false, false, true, diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index 1bce3c6bb2..cf8efdea16 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -2552,6 +2552,7 @@ def create_route_maps(tgen, input_dict, build=False): nexthop = set_data.setdefault("nexthop", None) origin = set_data.setdefault("origin", None) ext_comm_list = set_data.setdefault("extcommunity", {}) + metrictype = set_data.setdefault("metric-type", {}) # Local Preference if local_preference: @@ -2559,6 +2560,10 @@ def create_route_maps(tgen, input_dict, build=False): "set local-preference {}".format(local_preference) ) + # Metric-Type + if metrictype: + rmap_data.append("set metric-type {}\n".format(metrictype)) + # Metric if metric: rmap_data.append("set metric {} \n".format(metric)) diff --git a/tests/topotests/ospf6_topo2/r1/ospf6d.conf b/tests/topotests/ospf6_topo2/r1/ospf6d.conf index 2e465e6d1f..1bf6550d9f 100644 --- a/tests/topotests/ospf6_topo2/r1/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r1/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,11 +27,11 @@ debug ospf6 asbr debug ospf6 nssa ! interface r1-eth0 + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! router ospf6 ospf6 router-id 10.254.254.1 area 0.0.0.1 stub - interface r1-eth0 area 0.0.0.1 ! diff --git a/tests/topotests/ospf6_topo2/r2/ospf6d.conf b/tests/topotests/ospf6_topo2/r2/ospf6d.conf index 4a1d10693d..7567c9cd64 100644 --- a/tests/topotests/ospf6_topo2/r2/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r2/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,14 +27,17 @@ debug ospf6 asbr debug ospf6 nssa ! interface r2-eth0 + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! interface r2-eth1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! interface r2-eth2 + ipv6 ospf6 area 0.0.0.2 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! @@ -42,7 +48,4 @@ router ospf6 default-information originate always metric 123 area 0.0.0.1 stub area 0.0.0.2 nssa - interface r2-eth0 area 0.0.0.1 - interface r2-eth1 area 0.0.0.0 - interface r2-eth2 area 0.0.0.2 ! diff --git a/tests/topotests/ospf6_topo2/r3/ospf6d.conf b/tests/topotests/ospf6_topo2/r3/ospf6d.conf index 5faeb70e56..0fb4e7e365 100644 --- a/tests/topotests/ospf6_topo2/r3/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r3/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,6 +27,7 @@ debug ospf6 asbr debug ospf6 nssa ! interface r3-eth0 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! @@ -31,5 +35,4 @@ router ospf6 ospf6 router-id 10.254.254.3 redistribute connected redistribute static - interface r3-eth0 area 0.0.0.0 ! diff --git a/tests/topotests/ospf6_topo2/r4/ospf6d.conf b/tests/topotests/ospf6_topo2/r4/ospf6d.conf index 04d763f6a8..91f8df440c 100644 --- a/tests/topotests/ospf6_topo2/r4/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r4/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,11 +27,11 @@ debug ospf6 asbr debug ospf6 nssa ! interface r4-eth0 + ipv6 ospf6 area 0.0.0.2 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! router ospf6 ospf6 router-id 10.254.254.4 area 0.0.0.2 nssa - interface r4-eth0 area 0.0.0.2 ! diff --git a/tests/topotests/ospf6_topo2/test_ospf6_topo2.py b/tests/topotests/ospf6_topo2/test_ospf6_topo2.py index 303bcd014d..eb8561c404 100644 --- a/tests/topotests/ospf6_topo2/test_ospf6_topo2.py +++ b/tests/topotests/ospf6_topo2/test_ospf6_topo2.py @@ -131,6 +131,8 @@ def build_topo(tgen): switch.add_link(tgen.gears["r2"]) switch.add_link(tgen.gears["r4"]) + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r4"], nodeif="r4-stubnet") def setup_module(mod): "Sets up the pytest environment" @@ -484,7 +486,7 @@ def test_area_filters(): pytest.skip(tgen.errors) # - # Configure import/export filters on r2 (ABR for area 1). + # Configure import/export filters on r2 (ABR for area 2). # config = """ configure terminal @@ -544,6 +546,102 @@ def test_area_filters(): expect_ospfv3_routes("r1", routes, wait=30, type="inter-area") +def test_nssa_range(): + """ + Test NSSA ABR ranges. + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Configure new addresses on r4 and enable redistribution of connected + # routes. + config = """ + configure terminal + interface r4-stubnet + ipv6 address 2001:db8:1000::1/128 + ipv6 address 2001:db8:1000::2/128 + router ospf6 + redistribute connected + """ + tgen.gears["r4"].vtysh_cmd(config) + logger.info("Expecting NSSA-translated external routes to be added on r3") + routes = {"2001:db8:1000::1/128": {}, "2001:db8:1000::2/128": {}} + expect_ospfv3_routes("r3", routes, wait=30, type="external-2") + + # Configure an NSSA range on r2 (ABR for area 2). + config = """ + configure terminal + router ospf6 + area 2 nssa range 2001:db8:1000::/64 + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting summarized routes to be removed from r3") + for route in ["2001:db8:1000::1/128", "2001:db8:1000::2/128"]: + test_func = partial(dont_expect_route, "r3", route, type="external-2") + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assertmsg = "{}'s {} summarized route still exists".format("r3", route) + assert result is None, assertmsg + logger.info("Expecting NSSA range to be added on r3") + routes = { + "2001:db8:1000::/64": { + "metricType":2, + "metricCost":20, + "metricCostE2":10, + }} + expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True) + + # Change the NSSA range cost. + config = """ + configure terminal + router ospf6 + area 2 nssa range 2001:db8:1000::/64 cost 1000 + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting NSSA range to be updated with new cost") + routes = { + "2001:db8:1000::/64": { + "metricType":2, + "metricCost":20, + "metricCostE2":1000, + }} + expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True) + + # Configure the NSSA range to not be advertised. + config = """ + configure terminal + router ospf6 + area 2 nssa range 2001:db8:1000::/64 not-advertise + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting NSSA summary route to be removed") + route = "2001:db8:1000::/64" + test_func = partial(dont_expect_route, "r3", route, type="external-2") + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assertmsg = "{}'s {} NSSA summary route still exists".format("r3", route) + assert result is None, assertmsg + + # Remove the NSSA range. + config = """ + configure terminal + router ospf6 + no area 2 nssa range 2001:db8:1000::/64 + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting previously summarized routes to be re-added") + routes = { + "2001:db8:1000::1/128": { + "metricType":2, + "metricCost":20, + }, + "2001:db8:1000::2/128": { + "metricType":2, + "metricCost":20, + }, + } + expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True) + + def teardown_module(_mod): "Teardown the pytest environment" tgen = get_topogen() diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py b/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py index 64dfa0c69d..f9fa55e275 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py @@ -669,89 +669,6 @@ def test_ospf_type5_summary_tc48_p0(request): result is True ), "Testcase {} : Failed" "Error: Summary missing in OSPF DB".format(tc_name) - step("Configure metric type as 1 in route map.") - - routemaps = { - "r0": { - "route_maps": { - "rmap_ipv4": [{"action": "permit", "set": {"metric-type": "type-1"}}] - } - } - } - result = create_route_maps(tgen, routemaps) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - step( - "Verify that external routes(static / connected) are summarised" - " to configured summary address with metric type 2." - ) - input_dict = { - SUMMARY["ipv4"][0]: { - "Summary address": SUMMARY["ipv4"][0], - "Metric-type": "E2", - "Metric": 20, - "Tag": 0, - "External route count": 5, - } - } - dut = "r0" - result = verify_ospf_summary(tgen, topo, dut, input_dict) - assert ( - result is True - ), "Testcase {} : Failed" "Error: Summary missing in OSPF DB".format(tc_name) - - step("Un configure metric type from route map.") - - routemaps = { - "r0": { - "route_maps": { - "rmap_ipv4": [ - { - "action": "permit", - "set": {"metric-type": "type-1"}, - "delete": True, - } - ] - } - } - } - result = create_route_maps(tgen, routemaps) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - step( - "Verify that external routes(static / connected) are summarised" - " to configured summary address with metric type 2." - ) - input_dict = { - SUMMARY["ipv4"][0]: { - "Summary address": SUMMARY["ipv4"][0], - "Metric-type": "E2", - "Metric": 20, - "Tag": 0, - "External route count": 5, - } - } - dut = "r0" - result = verify_ospf_summary(tgen, topo, dut, input_dict) - assert ( - result is True - ), "Testcase {} : Failed" "Error: Summary missing in OSPF DB".format(tc_name) - - step("Change rule from permit to deny in prefix list.") - pfx_list = { - "r0": { - "prefix_lists": { - "ipv4": { - "pf_list_1_ipv4": [ - {"seqid": 10, "network": "any", "action": "deny"} - ] - } - } - } - } - result = create_prefix_lists(tgen, pfx_list) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - write_test_footer(tc_name) diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index 14d8ac442e..c3faf22d17 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -109,7 +109,8 @@ static int interface_list_ioctl(void) unsigned int size; ifreq = (struct ifreq *)((caddr_t)ifconf.ifc_req + n); - ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT); + ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT, + VRF_DEFAULT_NAME); if_add_update(ifp); size = ifreq->ifr_addr.sa_len; if (size < sizeof(ifreq->ifr_addr)) @@ -119,7 +120,8 @@ static int interface_list_ioctl(void) } #else for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) { - ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT); + ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT, + VRF_DEFAULT_NAME); if_add_update(ifp); ifreq++; } diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index fa3aabb195..187cd10e9c 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -972,17 +972,9 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) link_nsid = ns_id_get_absolute(ns_id, link_nsid); } - /* Add interface. - * We add by index first because in some cases such as the master - * interface, we have the index before we have the name. Fixing - * back references on the slave interfaces is painful if not done - * this way, i.e. by creating by ifindex. - */ - ifp = if_get_by_ifindex(ifi->ifi_index, vrf_id); + ifp = if_get_by_name(name, vrf_id, NULL); set_ifindex(ifp, ifi->ifi_index, zns); /* add it to ns struct */ - if_set_name(ifp, name); - ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]); ifp->metric = 0; @@ -1814,7 +1806,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (ifp == NULL) { /* unknown interface */ - ifp = if_get_by_name(name, vrf_id); + ifp = if_get_by_name(name, vrf_id, NULL); } else { /* pre-configured interface, learnt now */ if (ifp->vrf_id != vrf_id) diff --git a/zebra/interface.c b/zebra/interface.c index a68d00d55c..595862a6c9 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1616,7 +1616,6 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) struct listnode *node; struct route_node *rn; struct zebra_if *zebra_if; - struct vrf *vrf; char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN]; zebra_if = ifp->info; @@ -1644,8 +1643,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) zebra_ptm_show_status(vty, NULL, ifp); - vrf = vrf_lookup_by_id(ifp->vrf_id); - vty_out(vty, " vrf: %s\n", vrf->name); + vty_out(vty, " vrf: %s\n", ifp->vrf->name); if (ifp->desc) vty_out(vty, " Description: %s\n", ifp->desc); @@ -1941,7 +1939,6 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, struct listnode *node; struct route_node *rn; struct zebra_if *zebra_if; - struct vrf *vrf; char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN]; char buf[BUFSIZ]; json_object *json_if; @@ -1979,8 +1976,7 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, zebra_ptm_show_status(vty, json, ifp); - vrf = vrf_lookup_by_id(ifp->vrf_id); - json_object_string_add(json_if, "vrfName", vrf->name); + json_object_string_add(json_if, "vrfName", ifp->vrf->name); if (ifp->desc) json_object_string_add(json_if, "description", ifp->desc); @@ -4206,21 +4202,19 @@ static int link_params_config_write(struct vty *vty, struct interface *ifp) static int if_config_write(struct vty *vty) { - struct vrf *vrf0; + struct vrf *vrf; struct interface *ifp; zebra_ptm_write(vty); - RB_FOREACH (vrf0, vrf_name_head, &vrfs_by_name) - FOR_ALL_INTERFACES (vrf0, ifp) { + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + FOR_ALL_INTERFACES (vrf, ifp) { struct zebra_if *if_data; struct listnode *addrnode; struct connected *ifc; struct prefix *p; - struct vrf *vrf; if_data = ifp->info; - vrf = vrf_lookup_by_id(ifp->vrf_id); if (ifp->vrf_id == VRF_DEFAULT) vty_frame(vty, "interface %s\n", ifp->name); diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index d9c69ceb6d..2db3e6e904 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -443,7 +443,8 @@ static int ifan_read(struct if_announcemsghdr *ifan) __func__, ifan->ifan_index, ifan->ifan_name); /* Create Interface */ - ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT); + ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT, + VRF_DEFAULT_NAME); if_set_index(ifp, ifan->ifan_index); if_get_metric(ifp); @@ -624,7 +625,8 @@ int ifm_read(struct if_msghdr *ifm) if (ifp == NULL) { /* Interface that zebra was not previously aware of, so * create. */ - ifp = if_create_name(ifname, VRF_DEFAULT); + ifp = if_get_by_name(ifname, VRF_DEFAULT, + VRF_DEFAULT_NAME); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("%s: creating ifp for ifindex %d", __func__, ifm->ifm_index); diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 06528d3dbe..5b79de9697 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -776,6 +776,13 @@ static void show_nexthop_json_helper(json_object *json_nexthop, break; } + /* This nexthop is a resolver for the parent nexthop. + * Set resolver flag for better clarity and delimiter + * in flat list of nexthops in json. + */ + if (nexthop->rparent) + json_object_boolean_true_add(json_nexthop, "resolver"); + if (nexthop->vrf_id != re->vrf_id) json_object_string_add(json_nexthop, "vrf", vrf_id_to_name(nexthop->vrf_id)); |
